From 4321361ad8537cc24bcd246464abb8f88ccbf412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Laboissi=C3=A8re?= Date: Sat, 17 Apr 2021 08:53:34 -0300 Subject: Import octave-communications_1.2.3.orig.tar.gz [dgit import orig octave-communications_1.2.3.orig.tar.gz] --- COPYING | 674 +++++ DESCRIPTION | 11 + INDEX | 148 ++ NEWS | 79 + doc/Makefile | 84 + doc/comms.info | 5650 ++++++++++++++++++++++++++++++++++++++++++ doc/comms.texi | 6462 ++++++++++++++++++++++++++++++++++++++++++++++++ doc/comms.txi | 2310 +++++++++++++++++ doc/commsimages.m | 87 + doc/images.mk | 22 + doc/images.sh | 29 + doc/mkdoc.pl | 160 ++ doc/mktexi.pl | 457 ++++ inst/@galois/conv.m | 85 + inst/@galois/convmtx.m | 47 + inst/@galois/deconv.m | 83 + inst/@galois/det.m | 26 + inst/@galois/dftmtx.m | 71 + inst/@galois/diag.m | 44 + inst/@galois/exp.m | 27 + inst/@galois/fft.m | 53 + inst/@galois/filter.m | 88 + inst/@galois/ifft.m | 54 + inst/@galois/inv.m | 28 + inst/@galois/inverse.m | 26 + inst/@galois/isequal.m | 36 + inst/@galois/log.m | 27 + inst/@galois/lu.m | 68 + inst/@galois/prod.m | 27 + inst/@galois/rank.m | 27 + inst/@galois/reshape.m | 58 + inst/@galois/roots.m | 76 + inst/@galois/sqrt.m | 27 + inst/@galois/sum.m | 27 + inst/@galois/sumsq.m | 33 + inst/ademodce.m | 191 ++ inst/amdemod.m | 95 + inst/ammod.m | 89 + inst/amodce.m | 176 ++ inst/apkconst.m | 147 ++ inst/awgn.m | 145 ++ inst/bchpoly.m | 239 ++ inst/berconfint.m | 66 + inst/bi2de.m | 96 + inst/bin2gray.m | 168 ++ inst/biterr.m | 176 ++ inst/bsc.m | 49 + inst/comms.m | 665 +++++ inst/compand.m | 121 + inst/convenc.m | 119 + inst/cosets.m | 57 + inst/de2bi.m | 157 ++ inst/decode.m | 295 +++ inst/deintrlv.m | 53 + inst/demodmap.m | 243 ++ inst/dpcmdeco.m | 49 + inst/dpcmenco.m | 113 + inst/dpcmopt.m | 86 + inst/egolaydec.m | 116 + inst/egolayenc.m | 71 + inst/egolaygen.m | 57 + inst/encode.m | 226 ++ inst/eyediagram.m | 210 ++ inst/fibodeco.m | 85 + inst/fiboenco.m | 99 + inst/fibosplitstream.m | 82 + inst/finddelay.m | 84 + inst/fmdemod.m | 63 + inst/fmmod.m | 92 + inst/gen2par.m | 55 + inst/genqammod.m | 59 + inst/gftable.m | 31 + inst/gfweight.m | 83 + inst/golombdeco.m | 99 + inst/golombenco.m | 112 + inst/hammgen.m | 80 + inst/helintrlv.m | 80 + inst/helscandeintrlv.m | 26 + inst/helscanintrlv.m | 70 + inst/huffmandeco.m | 112 + inst/huffmandict.m | 219 ++ inst/huffmanenco.m | 54 + inst/intrlv.m | 49 + inst/istrellis.m | 110 + inst/lloyds.m | 177 ++ inst/lz77deco.m | 82 + inst/lz77enco.m | 97 + inst/matdeintrlv.m | 36 + inst/matintrlv.m | 60 + inst/minpol.m | 85 + inst/modmap.m | 336 +++ inst/oct2dec.m | 61 + inst/pamdemod.m | 75 + inst/pammod.m | 81 + inst/poly2trellis.m | 253 ++ inst/prbs_generator.m | 72 + inst/prbs_iterator.m | 162 ++ inst/prbs_sequence.m | 97 + inst/pskdemod.m | 75 + inst/pskmod.m | 80 + inst/qamdemod.m | 48 + inst/qammod.m | 51 + inst/qaskdeco.m | 222 ++ inst/qaskenco.m | 182 ++ inst/qfunc.m | 36 + inst/qfuncinv.m | 35 + inst/quantiz.m | 71 + inst/randdeintrlv.m | 41 + inst/randerr.m | 114 + inst/randint.m | 100 + inst/randintrlv.m | 41 + inst/randsrc.m | 122 + inst/rcosfir.m | 141 ++ inst/reedmullerdec.m | 266 ++ inst/reedmullerenc.m | 58 + inst/reedmullergen.m | 87 + inst/ricedeco.m | 86 + inst/riceenco.m | 115 + inst/rledeco.m | 55 + inst/rleenco.m | 59 + inst/rsdecof.m | 99 + inst/rsencof.m | 119 + inst/rsgenpoly.m | 155 ++ inst/scatterplot.m | 168 ++ inst/shannonfanodeco.m | 150 ++ inst/shannonfanodict.m | 122 + inst/shannonfanoenco.m | 55 + inst/symerr.m | 149 ++ inst/systematize.m | 126 + inst/vec2mat.m | 63 + inst/wgn.m | 141 ++ src/Makefile.in | 69 + src/__errcore__.cc | 84 + src/__gfweight__.cc | 93 + src/aclocal.m4 | 291 +++ src/base-lu.cc | 191 ++ src/base-lu.h | 87 + src/bootstrap | 10 + src/config.h.in | 128 + src/configure | 5359 +++++++++++++++++++++++++++++++++++++++ src/configure.ac | 256 ++ src/cyclgen.cc | 282 +++ src/cyclpoly.cc | 286 +++ src/galois-def.cc | 135 + src/galois-def.h | 415 ++++ src/galois-ops.h | 151 ++ src/galois.cc | 1507 +++++++++++ src/galois.h | 209 ++ src/galoisfield.cc | 217 ++ src/galoisfield.h | 86 + src/genqamdemod.cc | 120 + src/gf.cc | 2843 +++++++++++++++++++++ src/isprimitive.cc | 157 ++ src/m4/octave-forge.m4 | 93 + src/op-gm-gm.cc | 168 ++ src/op-gm-m.cc | 143 ++ src/op-gm-s.cc | 144 ++ src/op-m-gm.cc | 143 ++ src/op-s-gm.cc | 148 ++ src/ov-galois.cc | 864 +++++++ src/ov-galois.h | 186 ++ src/primpoly.cc | 310 +++ src/syndtable.cc | 169 ++ src/undef-ah-octave.h | 27 + 164 files changed, 43707 insertions(+) create mode 100644 COPYING create mode 100644 DESCRIPTION create mode 100644 INDEX create mode 100644 NEWS create mode 100644 doc/Makefile create mode 100644 doc/comms.info create mode 100644 doc/comms.texi create mode 100644 doc/comms.txi create mode 100644 doc/commsimages.m create mode 100644 doc/images.mk create mode 100755 doc/images.sh create mode 100755 doc/mkdoc.pl create mode 100755 doc/mktexi.pl create mode 100644 inst/@galois/conv.m create mode 100644 inst/@galois/convmtx.m create mode 100644 inst/@galois/deconv.m create mode 100644 inst/@galois/det.m create mode 100644 inst/@galois/dftmtx.m create mode 100644 inst/@galois/diag.m create mode 100644 inst/@galois/exp.m create mode 100644 inst/@galois/fft.m create mode 100644 inst/@galois/filter.m create mode 100644 inst/@galois/ifft.m create mode 100644 inst/@galois/inv.m create mode 100644 inst/@galois/inverse.m create mode 100644 inst/@galois/isequal.m create mode 100644 inst/@galois/log.m create mode 100644 inst/@galois/lu.m create mode 100644 inst/@galois/prod.m create mode 100644 inst/@galois/rank.m create mode 100644 inst/@galois/reshape.m create mode 100644 inst/@galois/roots.m create mode 100644 inst/@galois/sqrt.m create mode 100644 inst/@galois/sum.m create mode 100644 inst/@galois/sumsq.m create mode 100644 inst/ademodce.m create mode 100644 inst/amdemod.m create mode 100644 inst/ammod.m create mode 100644 inst/amodce.m create mode 100644 inst/apkconst.m create mode 100644 inst/awgn.m create mode 100644 inst/bchpoly.m create mode 100644 inst/berconfint.m create mode 100644 inst/bi2de.m create mode 100644 inst/bin2gray.m create mode 100644 inst/biterr.m create mode 100644 inst/bsc.m create mode 100644 inst/comms.m create mode 100644 inst/compand.m create mode 100644 inst/convenc.m create mode 100644 inst/cosets.m create mode 100644 inst/de2bi.m create mode 100644 inst/decode.m create mode 100644 inst/deintrlv.m create mode 100644 inst/demodmap.m create mode 100644 inst/dpcmdeco.m create mode 100644 inst/dpcmenco.m create mode 100644 inst/dpcmopt.m create mode 100644 inst/egolaydec.m create mode 100644 inst/egolayenc.m create mode 100644 inst/egolaygen.m create mode 100644 inst/encode.m create mode 100644 inst/eyediagram.m create mode 100644 inst/fibodeco.m create mode 100644 inst/fiboenco.m create mode 100644 inst/fibosplitstream.m create mode 100644 inst/finddelay.m create mode 100644 inst/fmdemod.m create mode 100644 inst/fmmod.m create mode 100644 inst/gen2par.m create mode 100644 inst/genqammod.m create mode 100644 inst/gftable.m create mode 100644 inst/gfweight.m create mode 100644 inst/golombdeco.m create mode 100644 inst/golombenco.m create mode 100644 inst/hammgen.m create mode 100644 inst/helintrlv.m create mode 100644 inst/helscandeintrlv.m create mode 100644 inst/helscanintrlv.m create mode 100644 inst/huffmandeco.m create mode 100644 inst/huffmandict.m create mode 100644 inst/huffmanenco.m create mode 100644 inst/intrlv.m create mode 100644 inst/istrellis.m create mode 100644 inst/lloyds.m create mode 100644 inst/lz77deco.m create mode 100644 inst/lz77enco.m create mode 100644 inst/matdeintrlv.m create mode 100644 inst/matintrlv.m create mode 100644 inst/minpol.m create mode 100644 inst/modmap.m create mode 100644 inst/oct2dec.m create mode 100644 inst/pamdemod.m create mode 100644 inst/pammod.m create mode 100644 inst/poly2trellis.m create mode 100644 inst/prbs_generator.m create mode 100644 inst/prbs_iterator.m create mode 100644 inst/prbs_sequence.m create mode 100644 inst/pskdemod.m create mode 100644 inst/pskmod.m create mode 100644 inst/qamdemod.m create mode 100644 inst/qammod.m create mode 100644 inst/qaskdeco.m create mode 100644 inst/qaskenco.m create mode 100644 inst/qfunc.m create mode 100644 inst/qfuncinv.m create mode 100644 inst/quantiz.m create mode 100644 inst/randdeintrlv.m create mode 100644 inst/randerr.m create mode 100644 inst/randint.m create mode 100644 inst/randintrlv.m create mode 100644 inst/randsrc.m create mode 100644 inst/rcosfir.m create mode 100644 inst/reedmullerdec.m create mode 100644 inst/reedmullerenc.m create mode 100644 inst/reedmullergen.m create mode 100644 inst/ricedeco.m create mode 100644 inst/riceenco.m create mode 100644 inst/rledeco.m create mode 100644 inst/rleenco.m create mode 100644 inst/rsdecof.m create mode 100644 inst/rsencof.m create mode 100644 inst/rsgenpoly.m create mode 100644 inst/scatterplot.m create mode 100644 inst/shannonfanodeco.m create mode 100644 inst/shannonfanodict.m create mode 100644 inst/shannonfanoenco.m create mode 100644 inst/symerr.m create mode 100644 inst/systematize.m create mode 100644 inst/vec2mat.m create mode 100644 inst/wgn.m create mode 100644 src/Makefile.in create mode 100644 src/__errcore__.cc create mode 100644 src/__gfweight__.cc create mode 100644 src/aclocal.m4 create mode 100644 src/base-lu.cc create mode 100644 src/base-lu.h create mode 100755 src/bootstrap create mode 100644 src/config.h.in create mode 100755 src/configure create mode 100644 src/configure.ac create mode 100644 src/cyclgen.cc create mode 100644 src/cyclpoly.cc create mode 100644 src/galois-def.cc create mode 100644 src/galois-def.h create mode 100644 src/galois-ops.h create mode 100644 src/galois.cc create mode 100644 src/galois.h create mode 100644 src/galoisfield.cc create mode 100644 src/galoisfield.h create mode 100644 src/genqamdemod.cc create mode 100644 src/gf.cc create mode 100644 src/isprimitive.cc create mode 100644 src/m4/octave-forge.m4 create mode 100644 src/op-gm-gm.cc create mode 100644 src/op-gm-m.cc create mode 100644 src/op-gm-s.cc create mode 100644 src/op-m-gm.cc create mode 100644 src/op-s-gm.cc create mode 100644 src/ov-galois.cc create mode 100644 src/ov-galois.h create mode 100644 src/primpoly.cc create mode 100644 src/syndtable.cc create mode 100644 src/undef-ah-octave.h diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, 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 +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If 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 convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU 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 +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "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 PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM 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 PROGRAM (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 PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/DESCRIPTION b/DESCRIPTION new file mode 100644 index 0000000..dbb7b05 --- /dev/null +++ b/DESCRIPTION @@ -0,0 +1,11 @@ +Name: communications +Version: 1.2.3 +Date: 2021-04-02 +Author: various authors +Maintainer: Nir Krakauer +Title: Communications +Description: Digital Communications, Error Correcting Codes (Channel Code), Source Code functions, Modulation and Galois Fields +Depends: octave (>= 4.4), signal (>= 1.1.3) +Autoload: no +License: GPLv3+ +Url: http://octave.sf.net diff --git a/INDEX b/INDEX new file mode 100644 index 0000000..443a8ca --- /dev/null +++ b/INDEX @@ -0,0 +1,148 @@ +communications >> Communications +Random Signals + awgn + biterr + eyediagram + randerr + randint + randsrc + scatterplot + symerr + wgn + bsc +Source Coding + compand + dpcmdeco + dpcmenco + dpcmopt + huffmandeco + huffmandict + huffmanenco + lloyds + lz77deco + lz77enco + quantiz + shannonfanodict + shannonfanoenco + shannonfanodeco + rleenco + rledeco + riceenco + ricedeco + fiboenco + fibodeco + fibosplitstream + golombenco + golombdeco +Block Interleavers + intrlv + helscanintrlv + matintrlv + randintrlv + deintrlv + matdeintrlv + randdeintrlv +Block Coding + bchdeco + bchenco + bchpoly + convenc + cyclgen + cyclpoly + decode + encode + egolaydec + egolayenc + egolaygen + gen2par + hammgen + reedmullerdec + reedmullerenc + reedmullergen + rsgenpoly + rsdec + rsdecof + rsenc + rsencof + systematize + syndtable +Modulations + ademodce + amodce + ammod + amdemod + apkconst + bin2gray + demodmap + fmmod + fmdemod + genqammod + genqamdemod + modmap + pamdemod + pammod + pskdemod + pskmod + qaskdeco + qaskenco + qammod + qamdemod +Channel Filters + rcosfir +Galois Fields of Even Characteristic + + - = Addition and subtraction in a Galois Field. + * / \ = Matrix multiplication and division of Galois arrays. + .* ./ .\ = Element by element multiplication and division of Galois arrays. + ** ^ = Matrix exponentiation of Galois arrays. + .** .^ = Element by element matrix exponentiation of Galois arrays. + ' .' = Matrix transpose of Galois arrays. + == ~= != > >= < <= = Logical operators on Galois arrays. + all + any + cosets + conv + convmtx + deconv + det + dftmtx + diag + exp + gf + fft + filter + gftable + gfweight + ifft + inv + inverse + isequal + log + lu + prod + sqrt + rank + reshape + roots + sum + sumsq + isempty + isgalois + isprimitive + length + minpol + polyval + primpoly + size +Utility Functions + comms + bi2de + de2bi + oct2dec + istrellis + poly2trellis + vec2mat + qfunc + qfuncinv +Measurement and Analysis + berconfint + finddelay diff --git a/NEWS b/NEWS new file mode 100644 index 0000000..c9c2240 --- /dev/null +++ b/NEWS @@ -0,0 +1,79 @@ + +Summary of important user-visible changes for communications (next release): +------------------------------------------------------------------ + + +Summary of important user-visible changes for communications 1.2.3: +------------------------------------------------------------------ + + ** The following functions are new: + + berconfint bin2gray finddelay rcosfir + + ** The function `poly2trellis' now supports feedback connections. + + ** Fixed a bug in 'de2bi' that gave an error when only specifying + input decimal and MSB direction, and also improved Matlab + compatibility of input option handling. + +Summary of important user-visible changes for communications 1.2.2: +------------------------------------------------------------------ + + ** The communications package is now compatible with Octave 4.4 and 5. + +Summary of important user-visible changes for communications 1.2.1: +------------------------------------------------------------------ + + ** The communications package is now compatible with Octave 4.0.0. + +Summary of important user-visible changes for communications 1.2.0: +------------------------------------------------------------------ + + ** The following functions are new: + + dpcmdeco istrellis + dpcmenco poly2trellis + dpcmopt + + ** The function `convenc' has been completely rewritten to be compatible + with Matlab. + + ** The plotting functions `eyediagram' and `scatterplot' have improved + Matlab compatibility. + + ** Fixed a bug in `egolaydec' which gave an error when there were more + than the three allowed erroneous bits, rather than setting the + error flag. + + ** Fixed a bug in `oct2dec' to handle large numbers properly. + + ** Fixed a bug in `quantiz' which gave incorrect results when the lookup + table has one element. + +Summary of important user-visible changes for communications 1.1.1: +------------------------------------------------------------------ + + ** The function `marcumq' has been moved to the signal package + + ** communications is no longer dependent on the image package + + ** The following functions are new: + + convenc + + ** The following functions have improved Matlab compatibility and tests: + bi2de + de2bi + oct2dec + + ** The function `reedmullerdec' had a bug fix introduced on the + previous release + + ** The function `huffmandeco' has been rewritten and made more + efficient and should perform faster + + ** Fixed bug in `glu' which made it unusable + + ** Use of deprecated functions has been removed + + ** Package is no longer automatically loaded. diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000..c339af3 --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,84 @@ +DVIPS = dvips +LN_S = ln -s +MAKEINFO = makeinfo +OCTAVE = octave +PERL = perl +TEXI2DVI = texi2dvi +TEXI2HTML = makeinfo --html +TEXI2PDF = texi2pdf + +INFODOC = comms.info +DVIDOC = $(patsubst %.info,%.dvi,$(INFODOC)) +PSDOC = $(patsubst %.info,%.ps,$(INFODOC)) +PDFDOC = $(patsubst %.info,%.pdf,$(INFODOC)) +HTMLDOC = $(patsubst %.info,%.html,$(INFODOC)) +TEXIDOC = $(patsubst %.info,%.texi,$(INFODOC)) +DOCSTRINGS = DOCSTRINGS +INDEX = ../INDEX + +all: info +info: $(INFODOC) +dvi: $(DVIDOC) +html: $(HTMLDOC) +pdf: $(PDFDOC) +ps: $(PSDOC) + +%.dvi: %.texi + $(TEXI2DVI) --clean -o $@ $< + +%.info: %.texi + $(MAKEINFO) --no-split -o $@ $< + +%.pdf: %.texi + $(TEXI2PDF) --clean -o $@ $< + +%.ps: %.dvi + $(DVIPS) -o $@ $< + +%.html: %.texi + rm -rf $(@:.html=.htp) + if $(TEXI2HTML) -o $(@:.html=.htp) $<; then \ + rm -rf $@ && mv $(@:.html=.htp) $@; \ + else \ + rm -rf $(@:.html=.htp); exit 1; \ + fi + +.PRECIOUS: %.texi +%.texi : %.txi + @echo "Making texinfo $@"; \ + $(RM) -f $(DOCSTRINGS); \ + $(PERL) ./mkdoc.pl ../ > $(DOCSTRINGS); \ + $(PERL) ./mktexi.pl $< $(DOCSTRINGS) $(INDEX) > $@ ; \ + $(RM) -f $(DOCSTRINGS); + +# Auxiliary make file defines build rules for generated images for the manual +-include images.mk +images.mk: images.sh + $(SHELL) $< > $@ + +$(DVIDOC): $(IMAGES_EPS) +$(PDFDOC): $(IMAGES_PDF) + +HTMLDIR_IMAGES = $(addprefix $(HTMLDOC)/,$(IMAGES_PNG)) +$(HTMLDIR_IMAGES): $(IMAGES_PNG) | $(HTMLDOC) + cp $(@F) $@ + +html: $(HTMLDIR_IMAGES) + +# The images included in the HTML manual must be present before the makeinfo +# command is invoked or it will fall back on incorrect file names. +$(HTMLDOC): $(IMAGES_PNG) + +# The texi2dvi script (used to create both PDF and DVI output formats) +# uses some fixed temporary file names. In order to avoid a race condition +# the DVI and PDF builds are forced to run serially through a Makefile rule. +$(PDFDOC): $(DVIDOC) + +clean: + rm -rf comms.t2d comms.t2p + +maintainer-clean: clean + rm -rf *.dvi *.eps *.html *.info *.pdf *.ps *.png *.texi + rm -f images.mk + +.PHONY: all clean dvi html info maintainer-clean pdf ps diff --git a/doc/comms.info b/doc/comms.info new file mode 100644 index 0000000..59c518e --- /dev/null +++ b/doc/comms.info @@ -0,0 +1,5650 @@ +This is comms.info, produced by makeinfo version 6.7 from comms.texi. + + +File: comms.info, Node: Top, Next: Introduction, Up: (dir) + +Communications Package for Octave +********************************* + +* Menu: + +* Introduction:: +* Random Signals:: +* Source Coding:: +* Block Coding:: +* Convolutional Coding:: +* Modulations:: +* Special Filters:: +* Galois Fields:: +* Function Reference:: + + +File: comms.info, Node: Introduction, Next: Random Signals, Prev: Top, Up: Top + +1 Introduction +************** + +This is the manual for the Communications Package for GNU Octave. All +functions provided by this package are described in this manual. In +addition many functions from Octave and other Octave packages are useful +to or required by this package, and so they may also be explained or +shown in examples in this manual. + + This documentation is a work in progress, you are invited to help +improve it and submit patches. + + +File: comms.info, Node: Random Signals, Next: Source Coding, Prev: Introduction, Up: Top + +2 Random Signals +**************** + +The purpose of the functions described here is to create and add random +noise to a signal, to create random data and to analyze the eventually +errors in a received signal. The functions to perform these tasks can +be considered as either related to the creation or analysis of signals +and are treated separately below. + + It should be noted that the examples below are based on the output of +a random number generator, and so the user can not expect to exactly +recreate the examples below. + +* Menu: + +* Signal Creation:: +* Signal Analysis:: + + +File: comms.info, Node: Signal Creation, Next: Signal Analysis, Up: Random Signals + +2.1 Signal Creation +=================== + +The signal creation functions here fall into to two classes. Those that +treat discrete data and those that treat continuous data. The basic +function to create discrete data is 'randint', that creates a random +matrix of equi-probable integers in a desired range. For example + + octave:1> a = randint (3, 3, [-1, 1]) + a = + + 0 1 0 + -1 -1 1 + 0 1 1 + +creates a 3-by-3 matrix of random integers in the range -1 to 1. To +allow for repeated analysis with the same random data, the function +'randint' allows the seed-value of the random number generator to be +set. For instance + + octave:1> a = randint (3, 3, [-1, 1], 1) + a = + + 0 1 1 + 0 -1 0 + 1 -1 -1 + +will always produce the same set of random data. The range of the +integers to produce can either be a two element vector or an integer. +In the case of a two element vector all elements within the defined +range can be produced. In the case of an integer range M, 'randint' +returns the equi-probable integers in the range [0:2^M-1]. + + The function 'randsrc' differs from 'randint' in that it allows a +random set of symbols to be created with a given probability. The +symbols can be real, complex or even characters. However characters and +scalars can not be mixed. For example + + octave:1> a = randsrc (2, 2, "ab"); + octave:2> b = randsrc (4, 4, [1, 1i, -1, -1i]); + +are both legal, while + + octave:1> a = randsrc (2, 2, [1, "a"]); + +is not legal. The alphabet from which the symbols are chosen can be +either a row vector or two row matrix. In the case of a row vector, all +of the elements of the alphabet are chosen with an equal probability. +In the case of a two row matrix, the values in the second row define the +probability that each of the symbols are chosen. For example + + octave:1> a = randsrc (5, 5, [1, 1i, -1, -1i; 0.6 0.2 0.1 0.1]) + a = + + 1 + 0i 0 + 1i 0 + 1i 0 + 1i 1 + 0i + 1 + 0i 1 + 0i 0 + 1i 0 + 1i 1 + 0i + -0 - 1i 1 + 0i -1 + 0i 1 + 0i 0 + 1i + 1 + 0i 1 + 0i 1 + 0i 1 + 0i 1 + 0i + -1 + 0i -1 + 0i 1 + 0i 1 + 0i 1 + 0i + +defines that the symbol '1' has a 60% probability, the symbol '1i' has a +20% probability and the remaining symbols have 10% probability each. +The sum of the probabilities must equal one. Like 'randint', 'randsrc' +accepts a fourth argument as the seed of the random number generator +allowing the same random set of data to be reproduced. + + The function 'randerr' allows a matrix of random bit errors to be +created, for binary encoded messages. By default, 'randerr' creates +exactly one errors per row, flagged by a non-zero value in the returned +matrix. That is + + octave:1> a = randerr (5, 10) + a = + + 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 1 + 0 0 0 0 0 0 0 0 0 1 + + The number of errors per row can be specified as the third argument +to 'randerr'. This argument can be either a scalar, a row vector or a +two row matrix. In the case of a scalar value, exactly this number of +errors will be created per row in the returned matrix. In the case of a +row vector, each element of the row vector gives a possible number of +equi-probable bit errors. The second row of a two row matrix defines +the probability of each number of errors occurring. For example + + octave:1> n = 15; k = 11; nsym = 100; + octave:2> msg = randint (nsym, k); ## Binary vector of message + octave:3> code = encode (msg, n, k, "bch"); + octave:4> berrs = randerr (nsym, n, [0, 1; 0.7, 0.3]); + octave:5> noisy = mod (code + berrs, 2) ## Add errors to coded message + +creates a vector MSG, encodes it with a [15,11] BCH code, and then add +either none or one error per symbol with the chances of an error being +30%. As previously, 'randerr' accepts a fourth argument as the seed of +the random number generator allowing the same random set of data to be +reproduced. + + All of the above functions work on discrete random signals. The +functions 'wgn' and 'awgn' create and add white Gaussian noise to +continuous signals. The function 'wgn' creates a matrix of white +Gaussian noise of a certain power. A typical call to 'wgn' is then + + octave:1> nse = wgn (10, 10, 0); + +which creates a 10-by-10 matrix of noise with a root mean squared power +of 0dBW relative to an impedance of 1 Ohm. + + This effectively means that an equivalent result to the above can be +obtained with + + octave:1> nse = randn (10, 10); + + The reference impedance and units of power to the function 'wgn' can +however be modified, for example + + octave:1> nse_30dBm_50Ohm = wgn (10000, 1, 30, 50, "dBm"); + octave:2> nse_0dBW_50Ohm = wgn (10000, 1, 0, 50, "dBW"); + octave:3> nse_1W_50Ohm = wgn (10000, 1, 1, 50, "linear"); + octave:4> [std(nse_30dBm_50Ohm), std(nse_0dBW_50Ohm), std(nse_1W_50Ohm)] + ans = + + 7.0805 7.1061 7.0730 + + Each of these produces a 1W signal referenced to a 50 Ohm impedance. +MATLAB uses the misnomer "dB" for "dBW", so "dB" is an accepted type for +'wgn' and is treated as a synonym for "dBW". + + In all cases, the returned matrix V, will be related to the input +power P and the impedance Z as + + P = sum (V(:) .^ 2 ) / IMP Watts + + By default 'wgn' produces real vectors of white noise. However, it +can produce both real and complex vectors like + + octave:1> rnse = wgn (10000, 1, 0, "dBm", "real"); + octave:2> cnse = wgn (10000, 1, 0, "dBm", "complex"); + octave:3> [std(rnse), std(real (cnse)), std(imag (cnse)), std(cnse)] + ans = + + 0.031615 0.022042 0.022241 0.031313 + +which shows that with a complex return value that the total power is the +same as a real vector, but that it is equally shared between the real +and imaginary parts. As previously, 'wgn' accepts a fourth numerical +argument as the seed of the random number generator allowing the same +random set of data to be reproduced. That is + + octave:1> nse = wgn (10, 10, 0, 0); + +will always produce the same set of data. + + The final function to deal with the creation of random signals is +'awgn', that adds noise at a certain level relative to a desired signal. +This function adds noise at a certain level to a desired signal. An +example call to 'awgn' is + + octave:1> x = [0:0.1:2*pi]; + octave:2> y = sin (x); + octave:3> noisy = awgn (y, 10, "measured") + +which adds noise with a 10dB signal-to-noise ratio to the measured power +in the desired signal. By default 'awgn' assumes that the desired +signal is at 0dBW, and the noise is added relative to this assumed +power. This behavior can be modified by the third argument to 'awgn'. +If the third argument is a numerical value, it is assumed to define the +power in the input signal, otherwise if the third argument is the string +"measured", as above, the power in the signal is measured prior to the +addition of the noise. + + The final argument to 'awgn' defines the definition of the power and +signal-to-noise ratio in a similar manner to 'wgn'. This final argument +can be either "dB" or "linear". In the first case the numerical value +of the input power is assumed to be in dBW and the signal-to-noise ratio +in dB. In the second case, the power is assumed to be in Watts and the +signal-to-noise ratio is expressed as a ratio. + + The return value of 'awgn' will be in the same form as the input +signal. In addition if the input signal is real, the additive noise +will be real. Otherwise the additive noise will also be complex and the +noise will be equally split between the real and imaginary parts. + + As previously the seed to the random number generator can be +specified as the last argument to 'awgn' to allow repetition of the same +scenario. That is + + octave:1> x = [0:0.1:2*pi]; + octave:2> y = sin (x); + octave:3> noisy = awgn (y, 10, "dB", 0, "measured") + +which uses the seed-value of 0 for the random number generator. + + +File: comms.info, Node: Signal Analysis, Prev: Signal Creation, Up: Random Signals + +2.2 Signal Analysis +=================== + +It is important to be able to evaluate the performance of a +communications system in terms of its bit-error and symbol-error rates. +Two functions 'biterr' and 'symerr' exist within this package to +calculate these values, both taking as arguments the expected and the +actually received data. The data takes the form of matrices or vectors, +with each element representing a single symbol. They are compared in +the following manner + +Both matrices + In this case both matrices must be the same size and then by + default the return values are the overall number of errors and the + overall error rate. +One column vector + In this case the column vector is used for comparison column-wise + with the matrix. The return values are row vectors containing the + number of errors and the error rate for each column-wise + comparison. The number of rows in the matrix must be the same as + the length of the column vector. +One row vector + In this case the row vector is used for comparison row-wise with + the matrix. The return values are column vectors containing the + number of errors and the error rate for each row-wise comparison. + The number of columns in the matrix must be the same as the length + of the row vector. + + For the bit-error comparison, the size of the symbol is assumed to be +the minimum number of bits needed to represent the largest element in +the two matrices supplied. However, the number of bits per symbol can +(and in the case of random data should) be specified. As an example of +the use of 'biterr' and 'symerr', consider the example + + octave:1> m = 8; + octave:2> msg = randint (10, 10, 2^m); + octave:3> noisy = mod (msg + diag (1:10), 2^m); + octave:4> [berr, brate] = biterr (msg, noisy, m) + berr = 32 + brate = 0.040000 + octave:5> [serr, srate] = symerr (msg, noisy) + serr = 10 + srate = 0.10000 + +which creates a 10-by-10 matrix adds 10 symbols errors to the data and +then finds the bit and symbol error-rates. + + Two other means of displaying the integrity of a signal are the +eye-diagram and the scatterplot. Although the functions 'eyediagram' +and 'scatterplot' have different appearance, the information presented +is similar and so are their inputs. The difference between 'eyediagram' +and 'scatterplot' is that 'eyediagram' segments the data into time +intervals and plots the in-phase and quadrature components of the signal +against this time interval. While 'scatterplot' uses a parametric plot +of quadrature versus in-phase components. + + Both functions can accept real or complex signals in the following +forms. + +A real vector + In this case the signal is assumed to be real and represented by + the vector X. +A complex vector + In this case the in-phase and quadrature components of the signal + are assumed to be the real and imaginary parts of the signal. +A matrix with two columns + In this case the first column represents the in-phase and the + second the quadrature components of a complex signal. + + An example of the use of the function 'eyediagram' is + + octave:1> n = 50; + octave:2> ovsp = 50; + octave:3> x = 1:n; + octave:4> xi = 1:1/ovsp:n-0.1; + octave:5> y = randsrc (1, n, [1 + 1i, 1 - 1i, -1 - 1i, -1 + 1i]); + octave:6> yi = interp1 (x, y, xi); + octave:7> noisy = awgn (yi, 15, "measured"); + octave:8> eyediagram (noisy, ovsp); + + Similarly an example of the use of the function 'scatterplot' is + + octave:1> n = 200; + octave:2> ovsp = 5; + octave:3> x = 1:n; + octave:4> xi = 1:1/ovsp:n-0.1; + octave:5> y = randsrc (1, n, [1 + 1i, 1 - 1i, -1 - 1i, -1 + 1i]); + octave:6> yi = interp1 (x, y, xi); + octave:7> noisy = awgn (yi, 15, "measured"); + octave:8> f = scatterplot (noisy, 1, 0, "b"); + octave:9> hold on; + octave:10> scatterplot (noisy, ovsp, 0, "r+", f); + + +File: comms.info, Node: Source Coding, Next: Block Coding, Prev: Random Signals, Up: Top + +3 Source Coding +*************** + +* Menu: + +* Quantization:: +* PCM Coding:: +* Arithmetic Coding:: +* Dynamic Range Compression:: + + +File: comms.info, Node: Quantization, Next: PCM Coding, Up: Source Coding + +3.1 Quantization +================ + +An important aspect of converting an analog signal to the digital domain +is quantization. This is the process of mapping a continuous signal to +a set of defined values. Octave contains two functions to perform +quantization, 'lloyds' creates an optimal mapping of the continuous +signal to a fixed number of levels and 'quantiz' performs the actual +quantization. + + The set of quantization points to use is represented by a +partitioning table (TABLE) of the data and the signal levels (CODES to +which they are mapped. The partitioning TABLE is monotonically +increasing and if x falls within the range given by two points of this +table then it is mapped to the corresponding code as seen in Table 1. + + Table 1: Table quantization partitioning and coding + + x < table(1) codes(1) + table(1) <= x < table(2) codes(2) + ... ... + table(i-1) <= x < table(i) codes(i) + ... ... + table(n-1) <= x < table(n) codes(n) + table(n-1) <= x codes(n+1) + + These partition and coding tables can either be created by the user +of using the function 'lloyds'. For instance the use of a linear +mapping can be seen in the following example. + + octave:1> m = 8; + octave:2> n = 1024; + octave:3> table = 2*[0:m-1]/m - 1 + 1/m; + octave:4> codes = 2*[0:m]/m - 1; + octave:5> x = 4*pi*[0:(n-1)]/(n-1); + octave:6> y = cos (x); + octave:7> [i, z] = quantiz (y, table, codes); + + If a training signal is known that well represents the expected +signals, the quantization levels can be optimized using the 'lloyds' +function. For example the above example can be continued + + octave:8> [table2, codes2] = lloyds (y, table, codes); + octave:9> [i, z2] = quantiz (y, table2, codes2); + +to use the mapping suggested by the function 'lloyds'. It should be +noted that the mapping given by 'lloyds' is highly dependent on the +training signal used. So if this signal does not represent a realistic +signal to be quantized, then the partitioning suggested by 'lloyds' will +be sub-optimal. + + +File: comms.info, Node: PCM Coding, Next: Arithmetic Coding, Prev: Quantization, Up: Source Coding + +3.2 PCM Coding +============== + +The DPCM function 'dpcmenco', 'dpcmdeco' and 'dpcmopt' implement a form +of predictive quantization, where the predictability of the signal is +used to further compress it. These functions are not yet implemented. + + +File: comms.info, Node: Arithmetic Coding, Next: Dynamic Range Compression, Prev: PCM Coding, Up: Source Coding + +3.3 Arithmetic Coding +===================== + +The arithmetic coding functions 'arithenco' and 'arithdeco' are not yet +implemented. + + +File: comms.info, Node: Dynamic Range Compression, Prev: Arithmetic Coding, Up: Source Coding + +3.4 Dynamic Range Compression +============================= + +The final source coding function is 'compand' which is used to compress +and expand the dynamic range of a signal. For instance consider a +logarithm quantized by a linear partitioning. Such a partitioning is +very poor for this large dynamic range. 'compand' can then be used to +compress the signal prior to quantization, with the signal being +expanded afterwards. For example + + octave:1> mu = 1.95; + octave:2> x = [0.01:0.01:2]; + octave:3> y = log (x); + octave:4> V = max (abs (y)); + octave:5> [i, z, d] = quantiz (y, [-4.875:0.25:0.875], [-5:0.25:1]); + octave:6> c = compand (y, minmu, V, "mu/compressor"); + octave:7> [i2, c2] = quantiz (c, [-4.875:0.25:0.875], [-5:0.25:1]); + octave:8> z2 = compand (c2, minmu, max (abs (c2)), "mu/expander"); + octave:9> d2 = sumsq (y - z2) / length (y); + octave:10> [d, d2] + ans = + + 0.0053885 0.0029935 + +which demonstrates that the use of 'compand' can significantly reduce +the distortion due to the quantization of signals with a large dynamic +range. + + +File: comms.info, Node: Block Coding, Next: Convolutional Coding, Prev: Source Coding, Up: Top + +4 Block Coding +************** + +The error-correcting codes available in this package are discussed here. +These codes work with blocks of data, with no relation between one block +and the next. These codes create codewords based on the messages to +transmit that contain redundant information that allow the recovery of +the original message in the presence of errors. + +* Menu: + +* Data Formats:: +* Binary Block Codes:: +* BCH Codes:: +* Reed-Solomon Codes:: + + +File: comms.info, Node: Data Formats, Next: Binary Block Codes, Up: Block Coding + +4.1 Data Formats +================ + +All of the codes described in this section are binary and share similar +data formats. The exception is the Reed-Solomon coder which has a +significantly longer codeword length in general and therefore uses a +different representation to efficiently pass data. The user should +refer to the section about the Reed-Solomon codes for the data format +used for Reed-Solomon codes. + + In general K bits of data are considered to represent a single +message symbol. These K bits are coded into N bits of data representing +the codeword. The data can therefore be grouped in one of three +manners, to emphasis this grouping into bits, messages and codewords + +A binary vector + Each element of the vector is either one or zero. If the data + represents an uncoded message the vector length should be an + integer number of K in length. +A binary matrix + In this case the data is ones and zeros grouped into rows, with + each representing a single message or codeword. The number of + columns in the matrix should be equal to K in the case of a uncoded + message or N in the case of a coded message. +A non-binary vector + In this case each element of the vector represents a message or + codeword in an integer format. The bits of the message or codeword + are represented by the bits of the vector elements with the + least-significant bit representing the first element in the message + or codeword. + + An example demonstrating the relationship between the three data +formats can be seen below. + + octave:1> k = 4; + octave:2> bin_vec = randint (k*10, 1); # Binary vector format + octave:3> bin_mat = reshape (bin_vec, k, 10)'; # Binary matrix format + octave:4> dec_vec = bi2de (bin_mat); # Decimal vector format + + The functions within this package will return data in the same format +to which it is given. It should be noted that internally the binary +matrix format is used, and thus if the message or codeword length is +large it is preferable to use the binary format to avoid internal +rounding errors. + + +File: comms.info, Node: Binary Block Codes, Next: BCH Codes, Prev: Data Formats, Up: Block Coding + +4.2 Binary Block Codes +====================== + +All of the codes presented here can be characterized by their + +Generator Matrix + A K-by-N matrix G to generate the codewords C from the messages T + by the matrix multiplication C = T * G. +Parity Check Matrix + A 'N-K'-by-N matrix H to check the parity of the received symbols. + If H * R = S != 0, then an error has been detected. S can be used + with the syndrome table to correct this error +Syndrome Table + A 2^K-by-N matrix ST with the relationship of the error vectors to + the non-zero parities of the received symbols. That is, if the + received symbol is represented as R = mod (T + E, 2), then the + error vector E is ST(S). + + It is assumed for most of the functions in this package that the +generator matrix will be in a 'standard' form. That is the generator +matrix can be represented by + + g(1,1) g(1,2) ... g(1,k) 1 0 ... 0 + g(2,1) g(2,2) g(2,k) 0 1 ... 0 + . . . . + . . . . + . . . . + g(k,1) g(k,2) ... g(k,k) 0 0 ... 1 + +or + + 1 0 ... 0 g(1,1) g(1,2) ... g(1,k) + 0 1 ... 0 g(2,1) g(2,2) g(2,k) + . . . . + . . . . + . . . . + 0 0 ... 1 g(k,1) g(k,2) ... g(k,k) + +and similarly the parity check matrix can be represented by a +combination of an identity matrix and a square matrix. + + Some of the codes can also have their representation in terms of a +generator polynomial that can be used to create the generator and parity +check matrices. In the case of BCH codes, this generator polynomial is +used directly in the encoding and decoding without ever explicitly +forming the generator or parity check matrix. + + The user can create their own generator and parity check matrices, or +they can rely on the functions 'hammgen', 'cyclgen' and 'cyclpoly'. The +function 'hammgen' creates parity check and generator matrices for +Hamming codes, while 'cyclpoly' and 'cyclgen' create generator +polynomials and matrices for generic cyclic codes. An example of their +use is + + octave:1> m = 3; + octave:2> n = 2^m - 1; + octave:2> k = 4; + octave:3> [par, gen] = hammgen (m); + octave:4> [par2, gen2] = cyclgen (n, cyclpoly (n, k)); + +which create identical parity check and generator matrices for the [7,4] +Hamming code. + + The syndrome table of the codes can be created with the function +'syndtable', in the following manner + + octave:1> [par, gen] = hammgen (3); + octave:2> st = syndtable (par); + + There exists two auxiliary functions 'gen2par' and 'gfweight', that +convert between generator and parity check matrices and calculate the +Hamming distance of the codes. For instance + + octave:1> par = hammgen (3); + octave:2> gen = gen2par (par); + octave:3> gfweight (gen) + ans = 3 + + It should be noted that for large values of N, the generator, parity +check and syndrome table matrices are very large. There is therefore an +internal limitation on the size of the block codes that can be created +that limits the codeword length N to less than 64. This is still +excessively large for the syndrome table, so use caution with these +codes. These limitations do not apply to the Reed-Solomon or BCH codes. + + The top-level encode and decode functions are 'encode' and 'decode', +which can be used with all codes, except the Reed-Solomon code. The +basic call to both of these functions passes the message to code/decode, +the codeword length, the message length and the type of coding to use. +There are four basic types that are available with these functions + +"linear" + Generic linear block codes +"cyclic" + Cyclic linear block codes +"hamming" + Hamming codes +"bch" + Bose Chaudhuri Hocquenghem (BCH) block codes + + It is not possible to distinguish between a binary vector and a +decimal vector coding of the messages that just happens to only have +ones and zeros. Therefore the functions 'encode' and 'decode' must be +told the format of the messages in the following manner. + + octave:1> m = 3; + octave:2> n = 7; + octave:3> k = 4; + octave:4> msg_bin = randint (10, k); + octave:5> cbin = encode (msg_bin, n, k, "hamming/binary"); + octave:5> cdec = encode (bi2de (msg), n, k, "hamming/decimal"); + +which codes a binary matrix and a non-binary vector representation of a +message, returning the coded message in the same format. The functions +'encode' and 'decode' by default accept binary coded messages. +Therefore "hamming" is equivalent to "hamming/binary". + + Except for the BCH codes, the function 'encode' and 'decode' +internally create the generator, parity check and syndrome table +matrices. Therefore if repeated calls to 'encode' and 'decode' are +made, it will often be faster to create these matrices externally and +pass them as an argument. For example + + n = 15; + k = 11; + [par, gen] = hammgen (4); + code1 = code2 = zeros (100, 15) + for i = 1:100 + msg = get_msg (i); + code1(i,:) = encode (msg, n, k, "linear", gen); # This is faster + code2(i,:) = encode (msg, n, k, "hamming"); # than this !!! + endfor + + In the case of the BCH codes the low-level functions described in the +next section are used directly by the 'encode' and 'decode' functions. + + +File: comms.info, Node: BCH Codes, Next: Reed-Solomon Codes, Prev: Binary Block Codes, Up: Block Coding + +4.3 BCH Codes +============= + +The BCH coder used here is based on code written by Robert +Morelos-Zaragoza (r.morelos-zaragoza@ieee.org). This code was +originally written in C and has been converted for use as an Octave +oct-file. + + Called without arguments, 'bchpoly' returns a table of valid BCH +error correcting codes and their error-correction capability. The first +returned column of 'bchpoly' is the codeword length, the second the +message length and the third the error correction capability of the +code. Called with one argument, 'bchpoly' returns similar output, but +only for the specified codeword length. In this manner codes with +codeword length greater than 511 can be found. + + In general the codeword length is of the form '2^M - 1', where M is +an integer. However if [N,K] is a valid BCH code, then it is also +possible to use a shortened BCH form of the form '[N-X,K-X]'. + + With two or more arguments, 'bchpoly' is used to find the generator +polynomial of a valid BCH code. For instance + + octave:1> bchpoly (15, 7) + ans = + + 1 0 0 0 1 0 1 1 1 + + octave:2> bchpoly (14, 6) + ans = + + 1 0 0 0 1 0 1 1 1 + +show that the generator polynomial of a [15,7] BCH code with the default +primitive polynomial is + + 1 + X ^ 4 + X ^ 6 + X ^ 7 + X ^ 8 + + Using a different primitive polynomial to define the Galois Field +over which the BCH code is defined results in a different generator +polynomial as can be seen in the example. + + octave:1> bchpoly ([1 1 0 0 1], 7) + ans = + + 1 0 0 0 1 0 1 1 1 + + octave:2> bchpoly ([1 0 0 1 1], 7) + ans = + + 1 1 1 0 1 0 0 0 1 + + It is recommend not to convert the generator polynomials created by +'bchpoly' into generator and parity check matrices with the BCH codes, +as the underlying BCH software is faster than the generic coding +software and can treat significantly longer codes. + + As well as using the 'encode' and 'decode' functions previously +discussed, the user can directly use the low-level BCH functions +'bchenco' and 'bchdeco'. In this case the messages must be in the +format of a binary matrix with K columns + + octave:1> n = 31; + octave:2> pgs = bchpoly (n); + octave:3> pg = pgs(floor (rand () * (rows (pgs) + 1)),:); # Pick a poly + octave:4> k = pg(2); + octave:5> t = pg(3); + octave:6> msg = randint (10, k); + octave:7> code = bchenco (msg, n, k); + octave:8> noisy = code + [ones(10, 1), zeros(10, n-1)]; + octave:9> dec = bchdeco (code, k, t); + + +File: comms.info, Node: Reed-Solomon Codes, Prev: BCH Codes, Up: Block Coding + +4.4 Reed-Solomon Codes +====================== + +* Menu: + +* Representation of Reed-Solomon Messages:: +* Creating and Decoding Messages:: +* Shortened Reed-Solomon Codes:: + + +File: comms.info, Node: Representation of Reed-Solomon Messages, Next: Creating and Decoding Messages, Up: Reed-Solomon Codes + +4.4.1 Representation of Reed-Solomon Messages +--------------------------------------------- + +The Reed-Solomon coder used in this package is based on code written by +Phil Karn (http://www.ka9q.net/code/fec). This code was originally +written in C and has been converted for use as an Octave oct-file. + + Reed-Solomon codes are based on Galois Fields of even characteristics +GF(2^M). Many of the properties of Galois Fields are therefore important +when considering Reed-Solomon coders. + + The representation of the symbols of the Reed-Solomon code differs +from the other block codes, in that the other block codes use a binary +representation, while the Reed-Solomon code represents each m-bit symbol +by an integer. The elements of the message and codeword must be +elements of the Galois Field corresponding to the Reed-Solomon code. +Thus to code a message with a [7,5] Reed-Solomon code an example is + + octave:1> m = 3; + octave:2> n = 7; + octave:3> k = 5; + octave:4> msg = gf (floor (2^m * rand (2, k)), m) + msg = + GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + + Array elements = + + 5 0 6 3 2 + 4 1 3 1 2 + + octave:5> code = rsenc (msg, n, k) + code = + GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + + Array elements = + + 5 0 6 3 2 3 5 + 4 1 3 1 2 6 3 + + The variable N is the codeword length of the Reed-Solomon coder, +while K is the message length. It should be noted that K should be less +than N and that 'N - K' should be even. The error correcting capability +of the Reed-Solomon code is then '(N - K)/2' symbols. M is the number +of bits per symbol, and is related to N by 'N = 2^M - 1'. For a valid +Reed-Solomon coder, M should be between 3 and 16. + + +File: comms.info, Node: Creating and Decoding Messages, Next: Shortened Reed-Solomon Codes, Prev: Representation of Reed-Solomon Messages, Up: Reed-Solomon Codes + +4.4.2 Creating and Decoding Messages +------------------------------------ + +The Reed-Solomon encoding function requires at least three arguments. +The first MSG is the message in encodes, the second is N the codeword +length and K is the message length. Therefore MSG must have K columns +and the output will have N columns of symbols. + + The message itself is many up of elements of a Galois Field GF(2^M). +Normally, The order of the Galois Field (M), is related to the codeword +length by 'N = 2^M - 1'. Another important parameter when determining +the behavior of the Reed-Solomon coder is the primitive polynomial of +the Galois Field (see 'gf'). Thus the messages + + octave:1> msg0 = gf ([0, 1, 2, 3], 3); + octave:2> msg1 = gf ([0, 1, 2, 3], 3, 13); + +will not result in the same Reed-Solomon coding. Finally, the parity of +the Reed-Solomon code are generated with the use of a generator +polynomial. The parity symbols are then generated by treating the +message to encode as a polynomial and finding the remainder of the +division of this polynomial by the generator polynomial. Therefore the +generator polynomial must have as many roots as 'N - K'. Whether the +parity symbols are placed before or afterwards the message will then +determine which end of the message is the most-significant term of the +polynomial representing the message. The parity symbols are therefore +different in these two cases. The position of the parity symbols can be +chosen by specifying "beginning" or "end" to 'rsenc' and 'rsdec'. By +default the parity symbols are placed after the message. + + Valid generator polynomials can be constructed with the 'rsgenpoly' +function. The roots of the generator polynomial are then defined by + + G = (X - A^(B*S)) * (X - A^((B+1)*S)) * ... * (X - A^((B+2*T-1)*S)). + +where T is '(N - K)/2', A is the primitive element of the Galois Field, +B is the first consecutive root, and S is the step between roots. +Generator polynomial of this form are constructed by 'rsgenpoly' and can +be passed to both 'rsenc' and 'rsdec'. It is also possible to pass the +B and S values directly to 'rsenc' and 'rsdec'. In the case of 'rsdec' +passing B and S can make the decoding faster. + + Consider the example below. + + octave:1> m = 8; + octave:2> n = 2^m - 1; + octave:3> k = 223; + octave:4> prim = 391; + octave:5> b = 112; + octave:6> s = 11; + octave:7> gg = rsgenpoly (n, k, prim, b, s); + octave:8> msg = gf (floor (2^m * rand (17, k)), m, prim); + octave:9> code = rsenc (msg, n, k, gg); + octave:10> noisy = code + [toeplitz([ones(1,17)], zeros(1,17)), zeros(17,238)]; + octave:11> [dec, nerr] = rsdec (msg, n, k, b, s); + octave:12> nerr' + ans = + + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 -1 + + octave:13> any (msg' != dec') + ans = + + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 + + This is an interesting example in that it demonstrates many of the +additional arguments of the Reed-Solomon functions. In particular this +example approximates the CCSDS standard Reed-Solomon coder, lacking only +the dual-basis lookup tables used in this standard. The CCSDS uses +non-default values to all of the basic functions involved in the +Reed-Solomon encoding, since it has a non-default primitive polynomial, +generator polynomial, etc. + + The example creates 17 message blocks and adds between 1 and 17 error +symbols to these block. As can be seen NERR gives the number of errors +corrected. In the case of 17 introduced errors NERR equals -1, +indicating a decoding failure. This is normal as the correction ability +of this code is up to 16 error symbols. Comparing the input message and +the decoding it can be seen that as expected, only the case of 17 errors +has not been correctly decoded. + + +File: comms.info, Node: Shortened Reed-Solomon Codes, Prev: Creating and Decoding Messages, Up: Reed-Solomon Codes + +4.4.3 Shortened Reed-Solomon Codes +---------------------------------- + +In general the codeword length of the Reed-Solomon coder is chosen so +that it is related directly to the order of the Galois Field by the +formula 'N = 2^M - 1'. Although, the underlying Reed-Solomon coding +must operate over valid codeword length, there are sometimes reasons to +assume that the codeword length will be shorter. In this case the +message is padded with zeros before coding, and the zeros are stripped +from the returned block. For example consider the shortened [6,4] +Reed-Solomon below + + octave:1> m = 3; + octave:2> n = 6; + octave:3> k = 4; + octave:4> msg = gf (floor (2^m * rand (2, k)), m) + msg = + GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + + Array elements = + + 7 0 2 5 + 1 5 7 1 + + octave:5> code = rsenc (msg, n, k) + code = + GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + + Array elements = + + 7 0 2 5 2 3 + 1 5 7 1 0 2 + + +File: comms.info, Node: Convolutional Coding, Next: Modulations, Prev: Block Coding, Up: Top + +5 Convolutional Coding +********************** + +Some initial support for convolutional codes is provided by the +functions described in this chapter. Convolutional codes are different +from block codes in that the sequence of preceding symbols is taken into +account when computing the output symbol of the coder. + +* Menu: + +* Trellis Structure:: +* Convolutional Encoding:: + + +File: comms.info, Node: Trellis Structure, Next: Convolutional Encoding, Up: Convolutional Coding + +5.1 Trellis Structure +===================== + +Like block codes, convolutional codes can be described by a set of +generator polynomials. Each polynomial describes the combination of +current and previous input symbols used to compute one output bit of the +encoder. + + The state transitions and outputs of a convolutional encoder can also +be described by a trellis diagram. This diagram describes the +transitions between states and the outputs of the encoder as a function +of the current state and the current input symbol. A trellis structure +can be created from a set of generator polynomials, specified as octal +numbers by convention, + + octave:1> g0 = 13; + octave:2> g1 = 17; + octave:3> trellis = poly2trellis (4, [g0, g1]); + +where G0 and G1 are the two polynomials of a rate 1/2 encoder with a +constraint length of 4. The returned trellis structure contains the +following fields + +'numInputSymbols' + The number of possible input symbols in the input sequence. +'numOutputSymbols' + The number of possible output symbols in the encoded sequence. +'numStates' + The number of possible states that the encoder can take. +'nextStates' + The state transition table for the encoder. Each row contains the + (zero-based) indices of the states reachable from the state + represented by that row for each possible input symbol. +'outputs' + The output table for the encoder. Each row contains the + (octal-encoded) output symbols produced by the encoder in the state + represented by that row for each possible input symbol. + + To check if a variable references a structure that is a valid trellis +describing a convolutional encoder, use the 'istrellis' function. + + +File: comms.info, Node: Convolutional Encoding, Prev: Trellis Structure, Up: Convolutional Coding + +5.2 Convolutional Encoding +========================== + +The convolutional encoding function takes the message to be encoded and +a trellis describing the encoder. The message must be a binary vector +containing an even number of symbols. For example, using the encoder +from the previous section, + + octave:1> trellis = poly2trellis (4, [13, 17]); + octave:2> msg = [1 1 0 1 1 0 0 0]; + octave:3> out = convenc (msg, trellis) + out = + + 1 1 1 0 1 0 1 1 0 1 1 0 0 0 1 1 + + The initial state of the encoder can also be passed in to 'convenc', +and the ending state can be read with an optional output argument. +Encoding a different vector with a different initial state using the +same encoder, + + octave:4> msg = [0 1 1 0 1 0 1 1]; + octave:5> [out, state] = convenc (msg, trellis, [], 4) + out = + + 0 1 0 0 0 1 1 0 1 1 1 0 0 0 0 1 + + state = 6 + +returns both the encoded array and the final state of the convolutional +encoder. This can be used to encode data in blocks, for example, saving +and restoring the internal state of the encoder for each subsequent +input block. + + +File: comms.info, Node: Modulations, Next: Special Filters, Prev: Convolutional Coding, Up: Top + +6 Modulations +************* + +To be written. + + Currently have functions amodce, ademodce, apkconst, demodmap, +modmap, qaskdeco, qaskenco, genqammod, pamdemod, pammod, pskdemod and +pskmod. + + +File: comms.info, Node: Special Filters, Next: Galois Fields, Prev: Modulations, Up: Top + +7 Special Filters +***************** + +To be written. + + +File: comms.info, Node: Galois Fields, Next: Function Reference, Prev: Special Filters, Up: Top + +8 Galois Fields +*************** + +* Menu: + +* Galois Field Basics:: +* Manipulating Galois Fields:: + + +File: comms.info, Node: Galois Field Basics, Next: Manipulating Galois Fields, Up: Galois Fields + +8.1 Galois Field Basics +======================= + +A Galois Field is a finite algebraic field. This package implements a +Galois Field type in Octave having 2^M members where M is an integer +between 1 and 16. Such fields are denoted as GF(2^M) and are used in +error correcting codes in communications systems. Galois Fields having +odd numbers of elements are not implemented. + + The _primitive element_ of a Galois Field has the property that all +elements of the Galois Field can be represented as a power of this +element. The _primitive polynomial_ is the minimum polynomial of some +primitive element in GF(2^M) and is irreducible and of order M. This +means that the primitive element is a root of the primitive polynomial. + + The elements of the Galois Field GF(2^M) are represented as the +values 0 to 2^M -1 by Octave. The first two elements represent the zero +and unity values of the Galois Field and are unique in all fields. The +element represented by 2 is the primitive element of the field and all +elements can be represented as combinations of the primitive element and +unity as follows + +Integer Binary Element of GF(2^M) +0 000 '0' +1 001 '1' +2 010 'A' +3 011 'A + 1' +4 100 'A^2' +5 101 'A^2 + 1' +6 110 'A^2 + A' +7 111 'A^2 + A + 1' + + It should be noted that there is often more than a single primitive +polynomial of GF(2^M). Each Galois Field over a different primitive +polynomial represents a different realization of the Field. The +representations above however rest valid. + +* Menu: + +* Creating Galois Fields:: +* Primitive Polynomials:: +* Accessing Internal Fields:: +* Function Overloading:: +* Known Problems:: + + +File: comms.info, Node: Creating Galois Fields, Next: Primitive Polynomials, Up: Galois Field Basics + +8.1.1 Creating Galois Fields +---------------------------- + +To work with a Galois Field GF(2^M) in Octave, you must first create a +variable that Octave recognizes as a Galois Field. This is done with +the function 'gf (A, M)' as follows. + + octave:1> a = [0:7]; + octave:2> b = gf (a, 4) + b = + GF(2^4) array. Primitive Polynomial = D^4+D+1 (decimal 19) + + Array elements = + + 0 1 2 3 4 5 6 7 + + This creates an array B with 8 elements that Octave recognizes as a +Galois Field. The field is created with the default primitive +polynomial for the field GF(2^4). It can be verified that a variable is +in fact a Galois Field with the functions 'isgalois' or 'whos'. + + octave:3> isgalois (a) + ans = 0 + octave:4> isgalois (b) + ans = 1 + octave:5> whos + Variables in the current scope: + + Attr Name Size Bytes Class + ==== ==== ==== ===== ===== + a 1x8 24 double + b 1x8 32 galois + + Total is 16 elements using 56 bytes + + It is also possible to create a Galois Field with an arbitrary +primitive polynomial. However, if the polynomial is not a primitive +polynomial of the field, and error message is returned. For instance. + + octave:1> a = [0:7]; + octave:2> b = gf (a, 4, 25) + b = + GF(2^4) array. Primitive Polynomial = D^4+D^3+1 (decimal 25) + + Array elements = + + 0 1 2 3 4 5 6 7 + + octave:3> c = gf (a, 4, 21) + error: gf: primitive polynomial (21) of Galois Field must be irreducible + + The function 'gftable' is included for compatibility with MATLAB. In +MATLAB this function is used to create the lookup tables used to +accelerate the computations over the Galois Field and store them to a +file. However Octave stores these parameters for all of the fields +currently in use and so this function is not required, although it is +silently accepted. + + +File: comms.info, Node: Primitive Polynomials, Next: Accessing Internal Fields, Prev: Creating Galois Fields, Up: Galois Field Basics + +8.1.2 Primitive Polynomials +--------------------------- + +The function 'gf (A, M)' creates a Galois Field using the default +primitive polynomial. However there exists many possible primitive +polynomials for most Galois Fields. Two functions exist for identifying +primitive polynomials, 'isprimitive' and 'primpoly'. 'primpoly (M, +OPT)' is used to identify the primitive polynomials of the fields +GF(2^M). For example + + octave:1> primpoly (4) + + Primitive polynomial(s) = + + D^4+D+1 + + ans = 19 + +identifies the default primitive polynomials of the field GF(2^M), which +is the same as 'primpoly (4, "min")'. All of the primitive polynomials +of a field can be identified with the function 'primpoly (M, "all")'. +For example + + octave:1> primpoly (4, "all") + + Primitive polynomial(s) = + + D^4+D+1 + D^4+D^3+1 + + ans = + + 19 25 + +while 'primpoly (M, "max")' returns the maximum primitive polynomial of +the field, which for the case above is 25. The function 'primpoly' can +also be used to identify the primitive polynomials having only a certain +number of non-zero terms. For instance + + octave:1> primpoly (5, 3) + + Primitive polynomial(s) = + + D^5+D^2+1 + D^5+D^3+1 + + ans = + + 37 41 + +identifies the polynomials with only three terms that can be used as +primitive polynomials of GF(2^5). If no primitive polynomials existing +having the requested number of terms then 'primpoly' returns an empty +vector. That is + + octave:1> primpoly (5, 2) + warning: primpoly: No primitive polynomial satisfies the given constraints + + ans = [](1x0) + + As can be seen above, 'primpoly' displays the polynomial forms the +the polynomials that it finds. This output can be suppressed with the +"nodisplay" option, while the returned value is left unchanged. + + octave:1> primpoly (4, "all", "nodisplay") + ans = + + 19 25 + + 'isprimitive (A)' identifies whether the elements of A can be used as +primitive polynomials of the Galois Fields GF(2^M). Consider as an +example the fields GF(2^4). The primitive polynomials of these fields +must have an order m and so their integer representation must be between +16 and 31. Therefore 'isprimitive' can be used in a similar manner to +'primpoly' as follows + + octave:1> find (isprimitive (16:31)) + 15 + ans = + + 19 25 + +which finds all of the primitive polynomials of GF(2^4). + + +File: comms.info, Node: Accessing Internal Fields, Next: Function Overloading, Prev: Primitive Polynomials, Up: Galois Field Basics + +8.1.3 Accessing Internal Fields +------------------------------- + +Once a variable has been defined as a Galois Field, the parameters of +the field of this structure can be obtained by adding a suffix to the +variable. Valid suffixes are '.m', '.prim_poly' and '.x', which return +the order of the Galois Field, its primitive polynomial and the data the +variable contains respectively. For instance + + octave:1> a = [0:7]; + octave:2> b = gf (a, 4); + octave:3> b.m + ans = 4 + octave:4> b.prim_poly + ans = 19 + octave:5> c = b.x; + octave:6> whos + Variables in the current scope: + + Attr Name Size Bytes Class + ==== ==== ==== ===== ===== + a 1x8 24 double + b 1x8 32 galois + c 1x8 64 double + + Total is 24 elements using 120 bytes + + Please note that it is explicitly forbidden to modify the Galois +field by accessing these variables. For instance + + octave:1> a = gf ([0:7], 3); + octave:2> a.prim_poly = 13; + +is explicitly forbidden. The result of this will be to replace the +Galois array A with a structure A with a single element called +'.prim_poly'. To modify the order or primitive polynomial of a field, a +new field must be created and the data copied. That is + + octave:1> a = gf ([0:7], 3); + octave:2> a = gf (a.x, a.m, 13); + + +File: comms.info, Node: Function Overloading, Next: Known Problems, Prev: Accessing Internal Fields, Up: Galois Field Basics + +8.1.4 Function Overloading +-------------------------- + +An important consideration in the use of the Galois Field package is +that many of the internal functions of Octave, such as 'roots', can not +accept Galois Fields as an input. This package therefore uses Octave +classes to _overload_ the internal Octave functions with equivalent +functions that work with Galois Fields, so that the standard function +names can be used. + + The version of the function that is chosen is determined by the first +argument of the function. This is a temporary situation until the +Galois Field class constructor can be rewritten to allow the use of the +'superiorto' function to define the galois class with a higher +precedence. So, considering the 'filter' function, if the first +argument is a _Matrix_, then the normal version of the function is +called regardless of whether the other arguments of the function are +Galois vectors or not. + + Other Octave functions work correctly with Galois Fields and so +overloaded versions are not necessary. This include such functions as +'size' and 'polyval'. + + It is also useful to use the '.x' option discussed in the previous +section, to extract the raw data of the Galois field for use with some +functions. An example is + + octave:1> a = minpol (gf (14, 5)); + octave:2> b = de2bi (a.x, [], "left-msb"); + +converts the polynomial form of the minimum polynomial of 14 in GF(2^5) +into an integer. Finally help for the Galois specific versions of the +functions must explicitly call the correct function as + + octave:1> help @galois/conv + + +File: comms.info, Node: Known Problems, Prev: Function Overloading, Up: Galois Field Basics + +8.1.5 Known Problems +-------------------- + +Please review the following list of known problems with the Galois type +before reporting a bug against this package. + +Saving and loading Galois variables + + Saving a Galois variable to a file is as simple as + + octave:1> a = gf (...); + octave:2> save a.mat a + + where A is any Galois variable. Galois variables can be saved in + the Octave binary and ASCII formats, as well as the HDF5 format. + To load a Galois variable from a file, the Galois type must already + be registered to the Octave interpreter prior to the call to + 'load'. If no Galois variables have been created yet, you will + have to do something like + + octave:1> dummy = gf (1); + octave:2> load a.mat + +Logarithm of zero does not return NaN + The logarithm of zero in a Galois field is not defined. However, + to avoid segmentation faults in later calculations the logarithm of + zero is defined as '2^M - 1', whose value is not the logarithm of + any other value in the Galois field. A warning is also shown to + tell the user about the problem. For example + + octave:1> m = 3; + octave:2> a = log (gf ([0:2^m-1], m)) + warning: log of zero undefined in Galois field + a = + GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + + Array elements = + + 7 0 1 3 2 6 4 5 + + To fix this problem would require a major rewrite of all code, + adding an exception for the case of NaN to all basic operators. + These exceptions will certainly slow the code down. + +Speed + The code was written piecemeal with no attention to optimization. + Some operations may be slower than they could be. Contributions + are welcome. + + +File: comms.info, Node: Manipulating Galois Fields, Prev: Galois Field Basics, Up: Galois Fields + +8.2 Manipulating Galois Fields +============================== + +* Menu: + +* Expressions manipulation and assignment:: +* Unary operations:: +* Arithmetic operations:: +* Comparison operations:: +* Polynomial manipulations:: +* Linear Algebra:: +* Signal Processing:: + + +File: comms.info, Node: Expressions manipulation and assignment, Next: Unary operations, Up: Manipulating Galois Fields + +8.2.1 Expressions, manipulation and assignment +---------------------------------------------- + +Galois variables can be treated in similar manner to other variables +within Octave. For instance Galois fields can be accessed using index +expressions in a similar manner to all other Octave matrices. For +example + + octave:1> a = gf ([[0:7]; [7:-1:0]], 3) + a = + GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + + Array elements = + + 0 1 2 3 4 5 6 7 + 7 6 5 4 3 2 1 0 + + octave:2> b = a(1,:) + b = + GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + + Array elements = + + 0 1 2 3 4 5 6 7 + + Galois arrays can equally use indexed assignments. That is, the data +in the array can be partially replaced, on the condition that the two +fields are identical. An example is + + octave:1> a = gf (ones (2, 8), 3); + octave:2> b = gf (zeros (1, 8), 3); + octave:3> a(1,:) = b + a = + GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + + Array elements = + + 0 0 0 0 0 0 0 0 + 1 1 1 1 1 1 1 1 + + Implicit conversions between normal matrices and Galois arrays are +possible. For instance data can be directly copied from a Galois array +to a real matrix as follows. + + octave:1> a = gf (ones (2, 8), 3); + octave:2> b = zeros (2, 8); + octave:3> b(2,:) = a(2,:) + b = + + 0 0 0 0 0 0 0 0 + 1 1 1 1 1 1 1 1 + + The inverse is equally possible, with the proviso that the data in +the matrix is valid in the Galois field. For instance + + octave:1> a = gf ([0:7], 3); + octave:2> a(1) = 1; + +is valid, while + + octave:1> a = gf ([0:7], 3); + octave:2> a(1) = 8; + +is not, since 8 is not an element of GF(2^3). This is a basic rule of +manipulating Galois arrays. That is matrices and scalars can be used in +conjunction with a Galois array as long as they contain valid data +within the Galois field. In this case they will be assumed to be of the +same field. + + Galois arrays can also be concatenated with real matrices or with +other Galois arrays in the same field. For example + + octave:1> a = [gf([0:7], 3); gf([7:-1:0], 3)]; + octave:2> b = [a, a]; + octave:3> c = [a, eye(2)]; + octave:3> whos + Variables in the current scope: + + Attr Name Size Bytes Class + ==== ==== ==== ===== ===== + a 2x8 64 galois + b 2x16 128 galois + c 2x10 80 galois + + Total is 68 elements using 272 bytes + + Other basic manipulations of Galois arrays are + +'isempty' + Returns true if the Galois array is empty. + +'size' + Returns the number of rows and columns in the Galois array. + +'length' + Returns the length of a Galois vector, or the maximum of rows or + columns of Galois arrays. + +'find' + Find the indexes of the non-zero elements of a Galois array. + +'diag' + Create a diagonal Galois array from a Galois vector, or extract a + diagonal from a Galois array. + +'reshape' + Change the shape of the Galois array. + + +File: comms.info, Node: Unary operations, Next: Arithmetic operations, Prev: Expressions manipulation and assignment, Up: Manipulating Galois Fields + +8.2.2 Unary operations +---------------------- + +The same unary operators that are available for normal Octave matrices +are also available for Galois arrays. These operations are + +'+X' + Unary plus. This operator has no effect on the operand. + +'-X' + Unary minus. Note that in a Galois Field this operator also has no + effect on the operand. + +'!X' + Returns true for zero elements of Galois Array. + +'X'' + Complex conjugate transpose. As the Galois Field only contains + integer values, this is equivalent to the transpose operator. + +'X.'' + Transpose of the Galois array. + + +File: comms.info, Node: Arithmetic operations, Next: Comparison operations, Prev: Unary operations, Up: Manipulating Galois Fields + +8.2.3 Arithmetic operations +--------------------------- + +The available arithmetic operations on Galois arrays are the same as on +other Octave matrices. It should be noted that both operands must be in +the same Galois Field. If one operand is a Galois array and the second +is a matrix or scalar, then the second operand is silently converted to +the same Galois Field. The element(s) of these matrix or scalar must +however be valid members of the Galois field. Thus + + octave:1> a = gf ([0:7], 3); + octave:2> b = a + [0:7]; + +is valid, while + + octave:1> a = gf ([0:7], 3); + octave:2> b = a + [1:8]; + +is not, since 8 is not a valid element of GF(2^3). The available +arithmetic operators are + +'X + Y' + Addition. If both operands are Galois arrays or matrices, the + number of rows and columns must both agree. If one operand is a is + a Galois array with a single element or a scalar, its value is + added to all the elements of the other operand. The '+' operator + on a Galois Field is equivalent to an exclusive-or on normal + integers. + +'X .+ Y' + Element by element addition. This operator is equivalent to '+'. + +'X - Y' + As both '+' and '-' in a Galois Field are equivalent to an + exclusive-or for normal integers, '-' is equivalent to the '+' + operator + +'X .- Y' + Element by element subtraction. This operator is equivalent to + '-'. + +'X * Y' + Matrix multiplication. The number of columns of X must agree with + the number of rows of Y. + +'X .* Y' + Element by element multiplication. If both operands are matrices, + the number of rows and columns must both agree. + +'X / Y' + Right division. This is conceptually equivalent to the expression + + (inverse (y') * x')' + + but it is computed without forming the inverse of Y'. + + If the matrix is singular then an error occurs. If the matrix is + under-determined, then a particular solution is found (but not + minimum norm). If the solution is over-determined, then an attempt + is made to find a solution, but this is not guaranteed to work. + +'X ./ Y' + Element by element right division. + +'X \ Y' + Left division. This is conceptually equivalent to the expression + + inverse (x) * y + + but it is computed without forming the inverse of X. + + If the matrix is singular then an error occurs. If the matrix is + under-determined, then a particular solution is found (but not + minimum norm). If the solution is over-determined, then an attempt + is made to find a solution, but this is not guaranteed to work. + +'X .\ Y' + Element by element left division. Each element of Y is divided by + each corresponding element of X. + +'X ^ Y' +'X ** Y' + Power operator. If X and Y are both scalars, this operator returns + X raised to the power Y. Otherwise X must be a square matrix + raised to an integer power. + +'X .^ Y' +'X .** Y' + Element by element power operator. If both operands are matrices, + the number of rows and columns must both agree. + + +File: comms.info, Node: Comparison operations, Next: Polynomial manipulations, Prev: Arithmetic operations, Up: Manipulating Galois Fields + +8.2.4 Comparison operations +--------------------------- + +Galois variables can be tested for equality in the usual manner. That +is + + octave:1> a = gf ([0:7], 3); + octave:2> a == ones (1, 8) + ans = + + 0 1 0 0 0 0 0 0 + + octave:3> a != zeros (1, 8) + ans = + + 0 1 1 1 1 1 1 1 + + Likewise, Galois vectors can be tested against scalar values (whether +they are Galois or not). For instance + + octave:4> a == 1 + ans = + + 0 1 0 0 0 0 0 0 + + To test if any or all of the values in a Galois array are non-zero, +the functions 'any' and 'all' can be used as normally. + + In addition the comparison operators '>', '>=', '<' and '<=' are +available. As elements of the Galois Field are modulus 2^M, all +elements of the field are both greater than and less than all others at +the same time. Thus these comparison operators don't make that much +sense and are only included for completeness. The comparison is done +relative to the integer value of the Galois Field elements. + + +File: comms.info, Node: Polynomial manipulations, Next: Linear Algebra, Prev: Comparison operations, Up: Manipulating Galois Fields + +8.2.5 Polynomial manipulations +------------------------------ + +A polynomial in GF(2^M) can be expressed as a vector in GF(2^M). For +instance if A is the _primitive element_, then the example + + octave:1> poly = gf ([2, 4, 5, 1], 3); + +represents the polynomial + + poly = A * x^3 + A^2 * x^2 + (A^2 + 1) * x + 1 + + Arithmetic can then be performed on these vectors. For instance to +add to polynomials an example is + + octave:1> poly1 = gf ([2, 4, 5, 1], 3); + octave:2> poly2 = gf ([1, 2], 3); + octave:3> sumpoly = poly1 + [0, 0, poly2] + sumpoly = + GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + + Array elements = + + 2 4 4 3 + + Note that POLY2 must be zero padded to the same length as poly1 to +allow the addition to take place. + + Multiplication and division of Galois polynomials is equivalent to +convolution and de-convolution of vectors of Galois elements. Thus to +multiply two polynomials in GF(2^3). + + octave:4> mulpoly = conv (poly1, poly2) + mulpoly = + GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + + Array elements = + + 2 0 6 0 2 + + Likewise the division of two polynomials uses the de-convolution +function as follows + + octave:5> [poly, remd] = deconv (mulpoly, poly2) + poly = + GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + + Array elements = + + 2 4 5 1 + + remd = + GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + + Array elements = + + 0 0 0 0 0 + + Note that the remainder of this division is zero, as we performed the +inverse operation to the multiplication. + + To evaluate a polynomial for a certain value in GF(2^M), use the +Octave function 'polyval'. + + octave:1> poly1 = gf ([2, 4, 5, 1], 3); ## a*x^3+a^2*x^2+(a^2+1)*x+1 + octave:2> x0 = gf ([0, 1, 2], 3); + octave:3> y0 = polyval (poly1, x0); + y0 = + GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + + Array elements = + + 1 2 0 + + octave:4> a = gf (2, 3); ## The primitive element + octave:5> y1 = a .* x0.^3 + a.^2 .* x0.^2 + (a.^2 + 1) .* x0 + 1 + y1 = + GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + + Array elements = + + 1 2 0 + + It is equally possible to find the roots of Galois polynomials with +the 'roots' function. Using the polynomial above over GF(2^3), we can +find its roots in the following manner + + octave:1> poly1 = gf ([2, 4, 5, 1], 3); + octave:2> root1 = roots (poly1) + root1 = + GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + + Array elements = + + 2 + 5 + 5 + + Thus the example polynomial has 3 roots in GF(2^3) with one root of +multiplicity 2. We can check this answer with the 'polyval' function as +follows + + octave:3> check1 = polyval (poly1, root1) + check1 = + GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + + Array elements = + + 0 + 0 + 0 + +which as expected gives a zero vector. It should be noted that both the +number of roots and their value, will depend on the chosen field. Thus +for instance + + octave:1> poly3 = gf ([2, 4, 5, 1], 3, 13); + octave:2> root3 = roots (poly3) + root3 = + GF(2^3) array. Primitive Polynomial = D^3+D^2+1 (decimal 13) + + Array elements = + + 5 + +shows that in the field GF(2^3) with a different primitive polynomial, +has only one root exists. + + The minimum polynomial of an element of GF(2^M) is the minimum degree +polynomial in GF(2), excluding the trivial zero polynomial, that has +that element as a root. The fact that the minimum polynomial is in +GF(2) means that its coefficients are one or zero only. The 'minpol' +function can be used to find the minimum polynomial as follows + + octave:1> a = gf (2, 3); ## The primitive element + octave:2> b = minpol (a) + b = + GF(2) array. + + Array elements = + + 1 0 1 1 + + Note that the minimum polynomial of the primitive element is the +primitive polynomial. Elements of GF(2^M) sharing the same minimum +polynomial form a partitioning of the field. This partitioning can be +found with the 'cosets' function as follows + + octave:1> c = cosets (3) + c = + { + [1,1] = + GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + + Array elements = + + 1 + + [1,2] = + GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + + Array elements = + + 2 4 6 + + [1,3] = + GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + + Array elements = + + 3 5 7 + + } + +which returns a cell array containing all of the elements of the +GF(2^3), partitioned into groups sharing the same minimum polynomial. +The function 'cosets' can equally accept a second argument defining the +primitive polynomial to use in its calculations (i.e. 'cosets (A, P)'). + + +File: comms.info, Node: Linear Algebra, Next: Signal Processing, Prev: Polynomial manipulations, Up: Manipulating Galois Fields + +8.2.6 Linear Algebra +-------------------- + +The basic linear algebra operation of this package is the LU +factorization of a Galois array. That is the Galois array A is +factorized in the following way + + octave:2> [l, u, p] = lu (a) + +such that 'P * A = L * U'. The matrix P contains row permutations of A, +such that L and U are strictly upper and low triangular. The Galois +array A can be rectangular. + + All other linear algebra operations within this package are based on +this LU factorization of a Galois array. An important consequence of +this is that no solution can be found for singular matrices, only a +particular solution will be found for under-determined systems of +equation and the solution found for over-determined systems is not +always correct. This is identical to the way MATLAB performs linear +algebra on Galois arrays. + + For instance consider the under-determined linear equation + + octave:1> A = gf ([2, 0, 3, 3; 3, 1, 3, 1; 3, 1, 1, 0], 2); + octave:2> b = [0:2]'; + octave:3> x = A \ b; + +gives the solution 'X = [2, 0, 3, 2]'. There are in fact 4 possible +solutions to this linear system; 'X = [3, 2, 2, 0]', 'X = [0, 3, 1, 1]', +'X = [2, 0, 3, 2]' and 'X = [1, 1, 0, 3]'. No particular selection +criteria are applied to the chosen solution. + + In addition, because singular matrices cannot be solved, unless you +know the matrix is not singular, you should test the determinant of the +matrix prior to solving the linear system. For instance + + octave:1> A = gf (floor (2^m * rand (3)), 2); + octave:2> b = [0:2]'; + octave:3> if (det (A) != 0); x = A \ b; y = b' / A; endif; + octave:4> r = rank (A); + +solves the linear systems 'A * X = B' and 'Y * A = B'. Note that you do +not need to take into account rounding errors in the determinant, as the +determinant can only take values within the Galois Field. So if the +determinant equals zero, the array is singular. + + +File: comms.info, Node: Signal Processing, Prev: Linear Algebra, Up: Manipulating Galois Fields + +8.2.7 Signal Processing with Galois Fields +------------------------------------------ + +Signal processing functions such as filtering, convolution, +de-convolution and Fourier transforms can be performed over Galois +Fields. For instance the 'filter' function can be used with Galois +vectors in the same manner as usual. For instance + + octave:1> b = gf ([2, 0, 0, 1, 0, 2, 0, 1], 2); + octave:2> a = gf ([2, 0, 1, 1], 2); + octave:3> x = gf ([1, zeros(1, 20)], 2); + octave:4> y = filter (b, a, x) + y = + GF(2^2) array. Primitive Polynomial = D^2+D+1 (decimal 7) + + Array elements = + + 1 0 3 0 2 3 1 0 1 3 3 1 0 1 3 3 1 0 1 3 3 + +gives the impulse response of the filter defined by A and B. + + Two equivalent ways are given to perform the convolution of two +Galois vectors. Firstly the function 'conv' can be used, or +alternatively the function 'convmtx' can be used. The first of these +function is identical to the convolution function over real vectors, and +has been described in the section about multiplying two Galois +polynomials. + + In the case where many Galois vectors will be convolved with the same +vector, the second function 'convmtx' offers an alternative method to +calculate the convolution. If A is a column vector and X is a column +vector of length N, then + + octave:1> m = 3; + octave:2> a = gf (floor (2^m * rand (4, 1)), m); + octave:3> b = gf (floor (2^m * rand (4, 1)), m); + octave:4> c0 = conv (a, b)'; + octave:5> c1 = convmtx (a, length (b)) * b; + octave:6> check = all (c0 == c1) + check = 1 + +shows the equivalence of the two functions. The de-convolution function +has been previously described above. + + The final signal processing function available in this package are +the functions to perform Fourier transforms over a Galois field. Three +functions are available, 'fft', 'ifft' and 'dftmtx'. The first two +functions use the third to perform their work. Given an element A of +the Galois field GF(2^M), 'dftmtx' returns the '2^M - 1' square matrix +used in the Fourier transforms with respect to A. The minimum +polynomial of A must be primitive in GF(2^M). In the case of the 'fft' +function 'dftmtx' is called with the primitive element of the Galois +Field as an argument. As an example + + octave:1> m = 4; + octave:2> n = 2^m - 1; + octave:2> alph = gf (2, m); + octave:3> x = gf (floor (2^m * rand (n, 1)), m); + octave:4> y0 = fft (x); + octave:5> y1 = dftmtx (alph) * x; + octave:6> z0 = ifft (y0); + octave:7> z1 = dftmtx (1/alph) * y1; + octave:8> check = all (y0 == y1) & all (z0 == x) & all (z1 == x) + check = 1 + + In all cases, the length of the vector to be transformed must be '2^M +-1'. As the 'dftmtx' creates a matrix representing the Fourier +transform, to limit the computational task only Fourier transforms in +GF(2^M), where M is less than or equal to 8, are supported. + + +File: comms.info, Node: Function Reference, Prev: Galois Fields, Up: Top + +9 Function Reference +******************** + +9.1 Functions Alphabetically +============================ + +* Menu: + +* ademodce:: Baseband demodulator for analog signals. +* amdemod:: Creates the AM demodulation of the signal S sampled at + frequency FS with carrier frequency FC +* ammod:: Creates the AM modulation of the amplitude signal X with + carrier frequency FC +* amodce:: Baseband modulator for analog signals. +* apkconst:: Plots a ASK/PSK signal constellation. +* awgn:: Add white Gaussian noise to a voltage signal +* bchdeco:: Decodes the coded message CODE using a BCH coder. +* bchenco:: Encodes the message MSG using a [N,K] BCH coding. +* bchpoly:: Calculates the generator polynomials for a BCH coder. +* berconfint:: Returns Bit Error Rate, BER, and confidence interval, + INTERVAL, for the number of errors R and number of + transmitted bits N with a confidence level of LEVEL. +* bi2de:: Convert bit matrix to a vector of integers +* bin2gray:: Creates a Gray encoded data Y with the same size as input X +* biterr:: Compares two matrices and returns the number of bit errors + and the bit error rate. +* bsc:: Send DATA into a binary symmetric channel with probability + P of error one each symbol +* comms:: Manual and test code for the Octave Communications toolbox. +* compand:: Compresses and expanding the dynamic range of a signal + using a mu-law or or A-law algorithm +* conv:: Convolve two Galois vectors +* convenc:: Encode the binary vector MSG with the convolutional encoder + described by the trellis structure T +* convmtx:: Create matrix to perform repeated convolutions with the + same vector in a Galois Field. +* cosets:: Finds the elements of GF(2^M) with primitive polynomial + PRIM, that share the same minimum polynomial. +* cyclgen:: Produce the parity check and generator matrix of a cyclic + code. +* cyclpoly:: This function returns the cyclic generator polynomials of + the code [N,K]. +* de2bi:: Convert a non-negative integer to bit vector +* decode:: Top level block decoder. +* deconv:: Deconvolve two Galois vectors +* deintrlv:: Restore elements of DATA according to ELEMENTS See also: + intrlv +* demodmap:: Demapping of an analog signal to a digital signal. +* det:: Compute the determinant of the Galois array A +* dftmtx:: Form a matrix, that can be used to perform Fourier + transforms in a Galois Field +* diag:: Return a diagonal matrix with Galois vector V on diagonal K + The second argument is optional. +* dpcmdeco:: Decode using differential pulse code modulation (DPCM) +* dpcmenco:: Encode using differential pulse code modulation (DPCM) +* dpcmopt:: Optimize the DPCM parameters and codebook +* egolaydec:: Decode Extended Golay code +* egolayenc:: Encode with Extended Golay code +* egolaygen:: Extended Golay code generator matrix +* encode:: Top level block encoder. +* exp:: Compute the anti-logarithm for each element of X for a + Galois array +* eyediagram:: Plot the eye-diagram of a signal. +* fft:: If X is a column vector, finds the FFT over the primitive + element of the Galois Field of X. +* fibodeco:: Returns the decoded Fibonacci value from the binary vectors + CODE Universal codes like Fibonacci codes have a useful + synchronization property, only for 255 maximum value we + have designed these routines. +* fiboenco:: Returns the cell-array of encoded Fibonacci value from the + column vectors NUM Universal codes like Fibonacci codes + have a useful synchronization property, only for 255 + maximum value we have designed these routines. +* fibosplitstream:: Returns the split data stream at the word boundaries + Assuming the stream was originally encoded using 'fiboenco' + and this routine splits the stream at the points where "11" + occur together & gives us the code-words which can later be + decoded from the 'fibodeco' This however doesn't mean that + we intend to verify if all the codewords are correct, and + in fact the last symbol in the return list can or can not + be a valid codeword +* filter:: Digital filtering of vectors in a Galois Field. +* finddelay:: Estimate the delay between times series X and time series Y + by correlating and finding the peak. +* fmdemod:: Creates the FM demodulation of the signal S sampled at + frequency FS with carrier frequency FC +* fmmod:: Creates the FM modulation S of the message signal M with + carrier frequency FC +* gen2par:: Converts binary generator matrix GEN to the parity check + matrix PAR and visa-versa. +* genqamdemod:: General quadrature amplitude demodulation. +* genqammod:: Modulates an information sequence of integers X in the + range '[0 ... M-1]' onto a quadrature amplitude modulated + signal Y, where 'M = length (c) - 1' and C is a 1D vector + specifying the signal constellation mapping to be used. +* gf:: #endif +* gftable:: This function exists for compatibility with matlab. +* gfweight:: Calculate the minimum weight or distance of a linear block + code. +* golombdeco:: Returns the Golomb decoded signal vector using CODE and M + Compulsory m is need to be specified. +* golombenco:: Returns the Golomb coded signal as cell array Also total + length of output code in bits can be obtained This function + uses a M need to be supplied for encoding signal vector + into a Golomb coded vector. +* hammgen:: Produce the parity check and generator matrices of a + Hamming code. +* helscanintrlv:: NROWS-by-NCOLS See also: helscandeintrlv +* huffmandeco:: Decode signal encoded by 'huffmanenco' +* huffmandict:: Builds a Huffman code, given a probability list. +* huffmanenco:: Returns the Huffman encoded signal using DICT. +* ifft:: If X is a column vector, finds the IFFT over the primitive + element of the Galois Field of X. +* intrlv:: Interleaved elements of DATA according to ELEMENTS See + also: deintrlv +* inv:: Compute the inverse of the square matrix A. +* inverse:: See inv +* isequal:: Return true if all of X1, X2, ... are equal See also: + isequalwithequalnans +* isgalois:: Return 1 if the value of the expression EXPR is a Galois + Field. +* isprimitive:: Returns 1 is the polynomial represented by A is a primitive + polynomial of GF(2). +* istrellis:: Return true if T is a valid trellis structure +* lloyds:: Optimize the quantization table and codes to reduce + distortion. +* log:: Compute the natural logarithm for each element of X for a + Galois array +* lu:: Compute the LU decomposition of A in a Galois Field. +* lz77deco:: Lempel-Ziv 77 source algorithm decoding implementation. +* lz77enco:: Lempel-Ziv 77 source algorithm implementation. +* matdeintrlv:: Restore elements of DATA with a temporary matrix of size + NROWS-by-NCOLS See also: matintrlv +* matintrlv:: Interleaved elements of DATA with a temporary matrix of + size NROWS-by-NCOLS See also: matdeintrlv +* minpol:: Finds the minimum polynomial for elements of a Galois + Field. +* modmap:: Mapping of a digital signal to an analog signal. +* oct2dec:: Convert octal to decimal values +* pamdemod:: Demodulates a pulse amplitude modulated signal X into an + information sequence of integers in the range '[0 ... M-1]' + PHI controls the initial phase and TYPE controls the + constellation mapping. +* pammod:: Modulates an information sequence of integers X in the + range '[0 ... M-1]' onto a pulse amplitude modulated signal + Y PHI controls the initial phase and TYPE controls the + constellation mapping. +* poly2trellis:: Convert convolutional code generator polynomials into + trellis form +* primpoly:: Finds the primitive polynomials in GF(2^M). +* prod:: Product of elements along dimension DIM of Galois array. +* pskdemod:: Demodulates a complex-baseband phase shift keying modulated + signal into an information sequence of integers in the + range '[0 ... M-1]'. +* pskmod:: Modulates an information sequence of integers X in the + range '[0 ... M-1]' onto a complex baseband phase shift + keying modulated signal Y. +* qamdemod:: Create the QAM demodulation of x with a size of alphabet m + See also: qammod, pskmod, pskdemod +* qammod:: Create the QAM modulation of x with a size of alphabet m + See also: qamdemod, pskmod, pskdemod +* qaskdeco:: Demaps an analog signal using a square QASK constellation. +* qaskenco:: Map a digital signal using a square QASK constellation. +* qfunc:: Compute the Q function See also: erfc, erf +* qfuncinv:: Compute the inverse Q function See also: erfc, erf +* quantiz:: Quantization of an arbitrary signal relative to a + partitioning +* randdeintrlv:: Restore elements of DATA with a random permutation See + also: randintrlv, intrlv, deintrlv +* randerr:: Generate a matrix of random bit errors. +* randint:: Generate a matrix of random binary numbers. +* randintrlv:: Interleaves elements of DATA with a random permutation See + also: intrlv, deintrlv +* randsrc:: Generate a matrix of random symbols. +* rank:: Compute the rank of the Galois array A by counting the + independent rows and columns +* rcosfir:: Implements a cosine filter or root cosine filter impulse + response +* reedmullerdec:: Decode the received code word VV using the RM-generator + matrix G, of order R, M, returning the code-word C. +* reedmullerenc:: Definition type construction of Reed-Muller code, of + order R, length 2^M. +* reedmullergen:: Definition type construction of Reed-Muller code, of + order R, length 2^M. +* reshape:: Return a matrix with M rows and N columns whose elements + are taken from the Galois array A. +* ricedeco:: Returns the Rice decoded signal vector using CODE and K + Compulsory K is need to be specified A restrictions is that + a signal set must strictly be non-negative The value of + code is a cell array of row-vectors which have the encoded + rice value for a single sample. +* riceenco:: Returns the Rice encoded signal using K or optimal K + Default optimal K is chosen between 0-7. +* rledeco:: Returns decoded run-length MESSAGE. +* rleenco:: Returns run-length encoded MESSAGE. +* roots:: For a vector V with N components, return the roots of the + polynomial over a Galois Field +* rsdec:: Decodes the message contained in CODE using a [N,K] + Reed-Solomon code. +* rsdecof:: Decodes an ASCII file using a Reed-Solomon coder. +* rsenc:: Encodes the message MSG using a [N,K] Reed-Solomon coding. +* rsencof:: Encodes an ASCII file using a Reed-Solomon coder. +* rsgenpoly:: Creates a generator polynomial for a Reed-Solomon coding + with message length of K and codelength of N. +* scatterplot:: Display the scatter plot of a signal. +* shannonfanodeco:: Returns the original signal that was Shannon-Fano + encoded. +* shannonfanodict:: Returns the code dictionary for source using + Shannon-Fano algorithm Dictionary is built from + SYMBOL_PROBABILITIES using the Shannon-Fano scheme. +* shannonfanoenco:: Returns the Shannon-Fano encoded signal using DICT This + function uses a DICT built from the 'shannonfanodict' and + uses it to encode a signal list into a Shannon-Fano code + Restrictions include a signal set that strictly belongs in + the 'range [1,N]' with 'N = length (dict)'. +* sqrt:: Compute the square root of X, element by element, in a + Galois Field See also: exp +* sum:: Sum of elements along dimension DIM of Galois array. +* sumsq:: Sum of squares of elements along dimension DIM of Galois + array If DIM is omitted, it defaults to 1 (column-wise sum + of squares) +* symerr:: Compares two matrices and returns the number of symbol + errors and the symbol error rate. +* syndtable:: Create the syndrome decoding table from the parity check + matrix H. +* systematize:: Given G, extract P parity check matrix. +* vec2mat:: Converts the vector V into a C column matrix with row + priority arrangement and with the final column padded with + the value D to the correct length. +* wgn:: Returns a M-by-N matrix Y of white Gaussian noise. + + +File: comms.info, Node: ademodce, Next: amdemod, Up: Function Reference + +9.1.1 ademodce +-------------- + + -- Function File: Y = ademodce (X, FS, "amdsb-tc", offset) + -- Function File: Y = ademodce (X, FS, "amdsb-tc/costas", offset) + -- Function File: Y = ademodce (X, FS, "amdsb-sc") + -- Function File: Y = ademodce (X, FS, "amdsb-sc/costas") + -- Function File: Y = ademodce (X, FS, "amssb") + -- Function File: Y = ademodce (X, FS, "qam") + -- Function File: Y = ademodce (X, FS, "qam/cmplx") + -- Function File: Y = ademodce (X, FS, "fm", DEV) + -- Function File: Y = ademodce (X, FS, "pm", DEV) + -- Function File: Y = ademodce (X, [FS, IPHS], ...) + -- Function File: Y = ademodce (..., NUM, DEN) + + Baseband demodulator for analog signals. The input signal is + specified by X, its sampling frequency by FS and the type of + modulation by the third argument, TYP. The default values of FS is + 1 and TYP is "amdsb-tc" + + If the argument FS is a two element vector, the first element + represents the sampling rate and the second the initial phase + + The different types of demodulations that are available are + + "am" + "amdsb-tc" + Double-sideband with carrier + "amdsb-tc/costas" + Double-sideband with carrier and Costas phase locked loop + "amdsb-sc" + Double-sideband with suppressed carrier + "amssb" + Single-sideband with frequency domain Hilbert filtering + "qam" + Quadrature amplitude demodulation. In-phase in odd-columns + and quadrature in even-columns + "qam/cmplx" + Quadrature amplitude demodulation with complex return value + "fm" + Frequency demodulation + "pm" + Phase demodulation + + Additional arguments are available for the demodulations + "amdsb-tc", "fm", "pm". These arguments are + + 'offset' + The offset in the input signal for the transmitted carrier + 'dev' + The deviation of the phase and frequency modulation + + It is possible to specify a low-pass filter, by the numerator NUM + and denominator DEN that will be applied to the returned vector + + See also: ademodce, dmodce + + +File: comms.info, Node: amdemod, Next: ammod, Prev: ademodce, Up: Function Reference + +9.1.2 amdemod +------------- + + -- Function File: M = amdemod (S, FC, FS) + Creates the AM demodulation of the signal S sampled at frequency FS + with carrier frequency FC + + Inputs: + * S: AM modulated signal + + * FC: carrier frequency + + * FS: sampling frequency + + Output: + * M: AM demodulation of the signal + + Demo + demo amdemod + See also: ammod, fmmod, fmdemod + + +File: comms.info, Node: ammod, Next: amodce, Prev: amdemod, Up: Function Reference + +9.1.3 ammod +----------- + + -- Function File: Y = ammod (X, FC, FS) + Creates the AM modulation of the amplitude signal X with carrier + frequency FC + + Inputs: + * X: amplitude message signal + + * FC: carrier frequency + + * FS: sampling frequency + + Output: + Y: The AM modulation of X + Demo + demo ammod + See also: amdemod, fmmod, fmdemod + + +File: comms.info, Node: amodce, Next: apkconst, Prev: ammod, Up: Function Reference + +9.1.4 amodce +------------ + + -- Function File: Y = amodce (X, FS, "amdsb-tc", offset) + -- Function File: Y = amodce (X, FS, "amdsb-sc") + -- Function File: Y = amodce (X, FS, "amssb") + -- Function File: Y = amodce (X, FS, "amssb/time", NUM, DEN) + -- Function File: Y = amodce (X, FS, "qam") + -- Function File: Y = amodce (X, FS, "fm", DEV) + -- Function File: Y = amodce (X, FS, "pm", DEV) + -- Function File: Y = amodce (X, [FS, IPHS], ...) + + Baseband modulator for analog signals. The input signal is + specified by X, its sampling frequency by FS and the type of + modulation by the third argument, TYP. The default values of FS is + 1 and TYP is "amdsb-tc" + + If the argument FS is a two element vector, the first element + represents the sampling rate and the second the initial phase + + The different types of modulations that are available are + + "am" + "amdsb-tc" + Double-sideband with carrier + "amdsb-sc" + Double-sideband with suppressed carrier + "amssb" + Single-sideband with frequency domain Hilbert filtering + "amssb/time" + Single-sideband with time domain filtering. Hilbert filter is + used by default, but the filter can be specified + "qam" + Quadrature amplitude modulation + "fm" + Frequency modulation + "pm" + Phase modulation + + Additional arguments are available for the modulations "amdsb-tc", + "fm", "pm" and "amssb/time". These arguments are + + 'offset' + The offset in the input signal for the transmitted carrier + 'dev' + The deviation of the phase and frequency modulation + 'num' + 'den' + The numerator and denominator of the filter transfer function + for the time domain filtering of the SSB modulation + + See also: ademodce, dmodce + + +File: comms.info, Node: apkconst, Next: awgn, Prev: amodce, Up: Function Reference + +9.1.5 apkconst +-------------- + + -- Function File: apkconst (NSIG) + -- Function File: apkconst (NSIG, AMP) + -- Function File: apkconst (NSIG, AMP, PHS) + -- Function File: apkconst (..., "n") + -- Function File: apkconst (..., STR) + -- Function File: Y = apkconst (...) + + Plots a ASK/PSK signal constellation. Argument NSIG is a real + vector whose length determines the number of ASK radii in the + constellation The values of vector NSIG determine the number of + points in each ASK radii + + By default the radii of each ASK modulated level is given by the + index of NSIG. The amplitudes can be defined explicitly in the + variable AMP, which is a vector of the same length as NSIG + + By default the first point in each ASK radii has zero phase, and + following points are coding in an anti-clockwise manner. If PHS is + defined then it is a vector of the same length as NSIG defining the + initial phase in each ASK radii + + In addition 'apkconst' takes two string arguments "n" and STR If + the string "n" is included in the arguments, then a number is + printed next to each constellation point giving the symbol value + that would be mapped to this point by the 'modmap' function. The + argument STR is a plot style string (example "r+") and determines + the default gnuplot point style to use for plot points in the + constellation + + If 'apkconst' is called with a return argument, then no plot is + created. However the return value is a vector giving the in-phase + and quadrature values of the symbols in the constellation See also: + dmod, ddemod, modmap, demodmap + + +File: comms.info, Node: awgn, Next: bchdeco, Prev: apkconst, Up: Function Reference + +9.1.6 awgn +---------- + + -- Function File: Y = awgn (X, SNR) + -- Function File: Y = awgn (X, SNR, PWR) + -- Function File: Y = awgn (X, SNR, PWR, SEED) + -- Function File: Y = awgn (..., TYPE) + + Add white Gaussian noise to a voltage signal + + The input X is assumed to be a real or complex voltage signal. The + returned value Y will be the same form and size as X but with + Gaussian noise added. Unless the power is specified in PWR, the + signal power is assumed to be 0dBW, and the noise of SNR dB will be + added with respect to this. If PWR is a numeric value then the + signal X is assumed to be PWR dBW, otherwise if PWR is "measured", + then the power in the signal will be measured and the noise added + relative to this measured power + + If SEED is specified, then the random number generator seed is + initialized with this value + + By default the SNR and PWR are assumed to be in dB and dBW + respectively. This default behavior can be chosen with TYPE set to + "dB". In the case where TYPE is set to "linear", PWR is assumed to + be in Watts and SNR is a ratio See also: randn, wgn + + +File: comms.info, Node: bchdeco, Next: bchenco, Prev: awgn, Up: Function Reference + +9.1.7 bchdeco +------------- + + -- Loadable Function: MSG = bchdeco (CODE, K, T) + -- Loadable Function: MSG = bchdeco (CODE, K, T, PRIM) + -- Loadable Function: MSG = bchdeco (..., PARPOS) + -- Loadable Function: [MSG, ERR] = bchdeco (...) + -- Loadable Function: [MSG, ERR, CCODE] = bchdeco (...) + Decodes the coded message CODE using a BCH coder. The message + length of the coder is defined in variable K, and the error + correction capability of the code is defined in T. + + The variable CODE is a binary array with N columns and an arbitrary + number of rows. Each row of CODE represents a single symbol to be + decoded by the BCH coder. The decoded message is returned in the + binary array MSG containing K columns and the same number of rows + as CODE. + + The use of 'bchdeco' can be seen in the following short example. + + m = 3; n = 2^m -1; k = 4; t = 1; + msg = randint (10, k); + code = bchenco (msg, n, k); + noisy = mod (randerr (10,n) + code, 2); + [dec, err] = bchdeco (msg, k, t); + + Valid codes can be found using 'bchpoly'. In general the codeword + length N should be of the form '2^M-1', where m is an integer. + However, shortened BCH codes can be used such that if '[2^M-1,K]' + is a valid code '[2^M-1-X,K-X]' is also a valid code using the same + generator polynomial. + + By default the BCH coding is based on the properties of the Galois + Field GF(2^M). The primitive polynomial used in the Galois can be + overridden by a primitive polynomial in PRIM. Suitable primitive + polynomials can be constructed with 'primpoly'. The form of PRIM + maybe be either a integer representation of the primitive + polynomial as given by 'primpoly', or a binary representation that + might be constructed like + + m = 3; + prim = de2bi (primpoly (m)); + + By default the parity symbols are assumed to be placed at the + beginning of the coded message. The variable PARPOS controls this + positioning and can take the values '"beginning\"' or '\"end\"'. + See also: bchpoly, bchenco, decode, primpoly + + +File: comms.info, Node: bchenco, Next: bchpoly, Prev: bchdeco, Up: Function Reference + +9.1.8 bchenco +------------- + + -- Loadable Function: CODE = bchenco (MSG, N, K) + -- Loadable Function: CODE = bchenco (MSG, N, K, G) + -- Loadable Function: CODE = bchenco (..., PARPOS) + Encodes the message MSG using a [N,K] BCH coding. The variable MSG + is a binary array with K columns and an arbitrary number of rows. + Each row of MSG represents a single symbol to be coded by the BCH + coder. The coded message is returned in the binary array CODE + containing N columns and the same number of rows as MSG. + + The use of 'bchenco' can be seen in the following short example. + + m = 3; n = 2^m -1; k = 4; + msg = randint (10,k); + code = bchenco (msg, n, k); + + Valid codes can be found using 'bchpoly'. In general the codeword + length N should be of the form '2^M-1', where m is an integer. + However, shortened BCH codes can be used such that if '[2^M-1,K]' + is a valid code '[2^M-1-X,K-X]' is also a valid code using the same + generator polynomial. + + By default the generator polynomial used in the BCH coding is based + on the properties of the Galois Field GF(2^M). This default + generator polynomial can be overridden by a polynomial in G. + Suitable generator polynomials can be constructed with 'bchpoly'. + + By default the parity symbols are placed at the beginning of the + coded message. The variable PARPOS controls this positioning and + can take the values '"beginning\"' or '\"end\"'. See also: + bchpoly, bchdeco, encode + + +File: comms.info, Node: bchpoly, Next: berconfint, Prev: bchenco, Up: Function Reference + +9.1.9 bchpoly +------------- + + -- Function File: P = bchpoly () + -- Function File: P = bchpoly (N) + -- Function File: P = bchpoly (N, K) + -- Function File: P = bchpoly (PRIM, K) + -- Function File: P = bchpoly (N, K, PRIM) + -- Function File: P = bchpoly (..., PROBE) + -- Function File: [P, F] = bchpoly (...) + -- Function File: [P, F, C] = bchpoly (...) + -- Function File: [P, F, C, PAR] = bchpoly (...) + -- Function File: [P, F, C, PAR, T] = bchpoly (...) + + Calculates the generator polynomials for a BCH coder. Called with + no input arguments 'bchpoly' returns a list of all of the valid BCH + codes for the codeword length 7, 15, 31, 63, 127, 255 and 511. A + three column matrix is returned with each row representing a + separate valid BCH code. The first column is the codeword length, + the second the message length and the third the error correction + capability of the code + + Called with a single input argument, 'bchpoly' returns the valid + BCH codes for the specified codeword length N. The output format + is the same as above + + When called with two or more arguments, 'bchpoly' calculates the + generator polynomial of a particular BCH code. The generator + polynomial is returned in P as a vector representation of a + polynomial in GF(2). The terms of the polynomial are listed + least-significant term first + + The desired BCH code can be specified by its codeword length N and + its message length K. Alternatively, the primitive polynomial over + which to calculate the polynomial can be specified as PRIM If a + vector representation of the primitive polynomial is given, then + PRIM can be specified as the first argument of two arguments, or as + the third argument. However, if an integer representation of the + primitive polynomial is used, then the primitive polynomial must be + specified as the third argument + + When called with two or more arguments, 'bchpoly' can also return + the factors F of the generator polynomial P, the cyclotomic coset + for the Galois field over which the BCH code is calculated, the + parity check matrix PAR and the error correction capability T. It + should be noted that the parity check matrix is calculated with + 'cyclgen' and limitations in this function means that the parity + check matrix is only available for codeword length up to 63. For + codeword length longer than this PAR returns an empty matrix + + With a string argument PROBE defined, the action of 'bchpoly' is to + calculate the error correcting capability of the BCH code defined + by N, K and PRIM and return it in P. This is similar to a call to + 'bchpoly' with zero or one argument, except that only a single code + is checked. Any string value for PROBE will force this action + + In general the codeword length N can be expressed as '2^M-1', where + M is an integer. However, if [N,K] is a valid BCH code, then a + shortened BCH code of the form [N-X,K-X] can be created with the + same generator polynomial + + See also: cyclpoly, encode, decode, cosets + + +File: comms.info, Node: berconfint, Next: bi2de, Prev: bchpoly, Up: Function Reference + +9.1.10 berconfint +----------------- + + -- Function File: BER = berconfint (R, N) + -- Function File: [BER, INTERVAL] = berconfint (R, N) + -- Function File: [BER, INTERVAL] = berconfint (R, N, LEVEL) + + Returns Bit Error Rate, BER, and confidence interval, INTERVAL, for + the number of errors R and number of transmitted bits N with a + confidence level of LEVEL. By default LEVEL is 0.95 + + The confidence interval is the Wilson one (without continuity + correction) for a proportion. By contrast, Matlab appears to + return the Clopper–Pearson confidence interval + + Reference: Robert G. Newcombe (1998), "Two‐sided confidence + intervals for the single proportion: comparison of seven methods", + Statistics in Medicine 17(8):857-872 + + +File: comms.info, Node: bi2de, Next: bin2gray, Prev: berconfint, Up: Function Reference + +9.1.11 bi2de +------------ + + -- Function File: D = bi2de (B) + -- Function File: D = bi2de (B, F) + -- Function File: D = bi2de (B, P) + -- Function File: D = bi2de (B, P, F) + + Convert bit matrix to a vector of integers + + Each row of the matrix B is treated as a single integer represented + in binary form. The elements of B, must therefore be '0' or '1' + + If P is defined then it is treated as the base of the decomposition + and the elements of B must then lie between '0' and 'p-1' + + The variable F defines whether the first or last element of B is + considered to be the most-significant. Valid values of F are + "right-msb" or "left-msb". By default F is "right-msb" + + See also: de2bi + + +File: comms.info, Node: bin2gray, Next: biterr, Prev: bi2de, Up: Function Reference + +9.1.12 bin2gray +--------------- + + -- Function File: [Y, MAPPING] = bin2gray (X, TYPE, M) + Creates a Gray encoded data Y with the same size as input X + + Input: + * X Binary matrix data + + * TYPE: The modulation type choices available:'qam', + 'pam','psk','dpsk', and 'fsk' + + * M: The modualtion order must be a power of 2 + + Output: + * Y: The gray data of the X data + * MAPPING: This provides the gray labesfor the given modulation + + Example + y = bin2gray ([0:3], 'qam', 16) + y = + + 0 + 1 + 3 + 2 + + Example with matrix + y = bin2gray ([0:3; 12:15], 'qam', 16) + y = + + 0 1 3 2 + 8 9 11 10 + See also: qammod + + +File: comms.info, Node: biterr, Next: bsc, Prev: bin2gray, Up: Function Reference + +9.1.13 biterr +------------- + + -- Function File: [NUM, RATE] = biterr (A, B) + -- Function File: [NUM, RATE] = biterr (..., K) + -- Function File: [NUM, RATE] = biterr (..., FLAG) + -- Function File: [NUM, RATE IND] = biterr (...) + + Compares two matrices and returns the number of bit errors and the + bit error rate. The binary representations of the variables A and + B are treated and A and B can be either: + + Both matrices + In this case both matrices must be the same size and then by + default the return values NUM and RATE are the overall number + of bit errors and the overall bit error rate + One column vector + In this case the column vector is used for bit error + comparison column-wise with the matrix. The returned values + NUM and RATE are then row vectors containing the number of bit + errors and the bit error rate for each of the column-wise + comparisons. The number of rows in the matrix must be the + same as the length of the column vector + One row vector + In this case the row vector is used for bit error comparison + row-wise with the matrix. The returned values NUM and RATE + are then column vectors containing the number of bit errors + and the bit error rate for each of the row-wise comparisons. + The number of columns in the matrix must be the same as the + length of the row vector + + This behavior can be overridden with the variable FLAG. FLAG can + take the value "column-wise", "row-wise" or "overall". A + column-wise comparison is not possible with a row vector and + visa-versa + + By default the number of bits in each symbol is assumed to be give + by the number required to represent the maximum value of A and B + The number of bits to represent a symbol can be overridden by the + variable K + + +File: comms.info, Node: bsc, Next: comms, Prev: biterr, Up: Function Reference + +9.1.14 bsc +---------- + + -- Function File: Y = bsc (DATA, P) + Send DATA into a binary symmetric channel with probability P of + error one each symbol + + +File: comms.info, Node: comms, Next: compand, Prev: bsc, Up: Function Reference + +9.1.15 comms +------------ + + -- Function File: comms ("help") + -- Function File: comms ("info") + -- Function File: comms ("info", MOD) + -- Function File: comms ("test") + -- Function File: comms ("test", MOD) + + Manual and test code for the Octave Communications toolbox. There + are 5 possible ways to call this function + + 'comms ("help")' + Display this help message. Called with no arguments, this + function also displays this help message + 'comms ("info")' + Open the Communications toolbox manual + 'comms ("info", MOD)' + Open the Communications toolbox manual at the section + specified by MOD + 'comms ("test")' + Run all of the test code for the Communications toolbox + 'comms ("test", MOD)' + Run only the test code for the Communications toolbox in the + module MOD + + Valid values for the variable MOD are + + "all" + All of the toolbox + "random" + The random signal generation and analysis package + "source" + The source coding functions of the package + "block" + The block coding functions + "convol" + The convolution coding package + "modulation" + The modulation package + "special" + The special filter functions + "galois" + The Galois fields package + + Please note that this function file should be used as an example of + the use of this toolbox + + +File: comms.info, Node: compand, Next: conv, Prev: comms, Up: Function Reference + +9.1.16 compand +-------------- + + -- Function File: Y = compand (X, MU, V, "mu/compressor") + -- Function File: Y = compand (X, MU, V, "mu/expander") + -- Function File: Y = compand (X, MU, V, "A/compressor") + -- Function File: Y = compand (X, MU, V, "A/expander") + + Compresses and expanding the dynamic range of a signal using a + mu-law or or A-law algorithm + + The mu-law compressor/expander for reducing the dynamic range, is + used if the fourth argument of 'compand' starts with "mu/". + Whereas the A-law compressor/expander is used if 'compand' starts + with "A/" The mu-law algorithm uses the formulation + + + V log (1 + \mu/V |x|) + y = -------------------- sgn(x) + log (1 + \mu) + + + while the A-law algorithm used the formulation + + + / A / (1 + log A) x, 0 <= |x| <= V/A + | + y = < V ( 1 + log (A/V |x|) ) + | ----------------------- sgn(x), V/A < |x| <= V + \ 1 + log A + + Neither converts from or to audio file ulaw format. Use mu2lin or + lin2mu instead + + See also: m2ulin, lin2mu + + +File: comms.info, Node: conv, Next: convenc, Prev: compand, Up: Function Reference + +9.1.17 conv +----------- + + -- Function File: conv (A, B) + Convolve two Galois vectors + + 'y = conv (a, b)' returns a vector of length equal to 'length (a) + + length (b) - 1' If A and B are polynomial coefficient vectors, + 'conv' returns the coefficients of the product polynomial See also: + deconv + + +File: comms.info, Node: convenc, Next: convmtx, Prev: conv, Up: Function Reference + +9.1.18 convenc +-------------- + + -- Function File: Y = convenc (MSG, T) + -- Function File: Y = convenc (MSG, T, PUNCT) + -- Function File: Y = convenc (MSG, T, PUNCT, S0) + -- Function File: [Y, STATE_END] = convenc (...) + Encode the binary vector MSG with the convolutional encoder + described by the trellis structure T + + The rate k/n convolutional encoder encodes k bits at a time from + the input vector and produces n bits at a time into the output + vector. The input MSG must have a length that is a multiple of k + + If the initial state S0 is specified, it indicates the internal + state of the encoder when the first k input bits are fed in. The + default value of S0 is 0 + + The optional output argument STATE_END indicates the internal state + of the encoder after the last bits are encoded. This allows the + state of the encoder to be saved and applied to the next call to + 'convenc' to process data in blocks + + See also: poly2trellis + + +File: comms.info, Node: convmtx, Next: cosets, Prev: convenc, Up: Function Reference + +9.1.19 convmtx +-------------- + + -- Function File: convmtx (A, N) + + Create matrix to perform repeated convolutions with the same vector + in a Galois Field. If A is a column vector and X is a column + vector of length N, in a Galois Field then + + 'convmtx (A, N) * X' + + gives the convolution of of A and X and is the same as 'conv (A, + X)'. The difference is if many vectors are to be convolved with + the same vector, then this technique is possibly faster + + Similarly, if A is a row vector and X is a row vector of length N, + then + + 'X * convmtx (A, N)' + + is the same as 'conv (X, A)' See also: conv + + +File: comms.info, Node: cosets, Next: cyclgen, Prev: convmtx, Up: Function Reference + +9.1.20 cosets +------------- + + -- Function File: cosets (M, PRIM) + + Finds the elements of GF(2^M) with primitive polynomial PRIM, that + share the same minimum polynomial. Returns a cell array of the + partitioning of GF(2^M) + + +File: comms.info, Node: cyclgen, Next: cyclpoly, Prev: cosets, Up: Function Reference + +9.1.21 cyclgen +-------------- + + -- Loadable Function: H = cyclgen (N, P) + -- Loadable Function: H = cyclgen (N, P, TYP) + -- Loadable Function: [H, G] = cyclgen (...) + -- Loadable Function: [H, G, K] = cyclgen (...) + Produce the parity check and generator matrix of a cyclic code. + The parity check matrix is returned as a M by N matrix, + representing the [N,K] cyclic code. M is the order of the + generator polynomial P and the message length K is given by 'N - + M'. + + The generator polynomial can either be a vector of ones and zeros, + and length M representing, + + P(1) + P(2) * x + P(3) * x^2 + ... + P(M) * x^(m-1) + + The terms of the polynomial are stored least-significant term + first. Alternatively, P can be an integer representation of the + same polynomial. + + The form of the parity check matrix is determined by TYP. If TYP + is 'system', a systematic parity check matrix is produced. If TYP + is 'nosys' and non-systematic parity check matrix is produced. + + If requested 'cyclgen' also returns the K by N generator matrix G. + See also: hammgen, gen2par, cyclpoly + + +File: comms.info, Node: cyclpoly, Next: de2bi, Prev: cyclgen, Up: Function Reference + +9.1.22 cyclpoly +--------------- + + -- Loadable Function: Y = cyclpoly (N, K) + -- Loadable Function: Y = cyclpoly (N, K, OPT) + -- Loadable Function: Y = cyclpoly (N, K, OPT, REP) + This function returns the cyclic generator polynomials of the code + [N,K]. By default the polynomial with the smallest weight is + returned. However this behavior can be overridden with the OPT + flag. Valid values of OPT are: + + '"all\"' + Returns all of the polynomials of the code [N,K] + '\"min\"' + Returns the polynomial of minimum weight of the code [N,K] + '\"max\"' + Returns the polynomial of the maximum weight of the code [N,K] + L + Returns the polynomials having exactly the weight L + + The polynomials are returns as row-vectors in the variable Y. Each + row of Y represents a polynomial with the least-significant term + first. The polynomials can be returned with an integer + representation if REP is '\"integer\"'. The default behavior is + given if REP is '\"polynomial\"'. See also: gf, isprimitive + + +File: comms.info, Node: de2bi, Next: decode, Prev: cyclpoly, Up: Function Reference + +9.1.23 de2bi +------------ + + -- Function File: B = de2bi (D) + -- Function File: B = de2bi (D, N) + -- Function File: B = de2bi (D, N, P) + -- Function File: B = de2bi (D, ..., F) + + Convert a non-negative integer to bit vector + + The variable D must be a vector of non-negative integers. 'de2bi' + then returns a matrix where each row represents the binary + representation of elements of D. If N is defined then the returned + matrix will have N columns. This number of columns can be either + larger than the minimum needed and zeros will be added to the msb + of the binary representation or smaller than the minimum in which + case the least-significant part of the element is returned + + If P is defined then it is used as the base for the decomposition + of the returned values. That is the elements of the returned value + are between '0' and 'p-1'. (P must have a value of 2 or higher.) + + The variable F defines whether the first or last element of B is + considered to be the most-significant. Valid values of F are + "right-msb" or "left-msb". By default F is "right-msb" + + See also: bi2de + + +File: comms.info, Node: decode, Next: deconv, Prev: de2bi, Up: Function Reference + +9.1.24 decode +------------- + + -- Function File: MSG = decode (CODE, N, K) + -- Function File: MSG = decode (CODE, N, K, TYP) + -- Function File: MSG = decode (CODE, N, K, TYP, OPT1) + -- Function File: MSG = decode (CODE, N, K, TYP, OPT1, OPT2) + -- Function File: [MSG, ERR] = decode (...) + -- Function File: [MSG, ERR, CCODE] = decode (...) + -- Function File: [MSG, ERR, CCODE, CERR] = decode (...) + + Top level block decoder. This function makes use of the lower + level functions such as 'cyclpoly', 'cyclgen', 'hammgen', and + 'bchenco'. The coded message to decode is pass in CODE, the + codeword length is N and the message length is K. This function is + used to decode messages using either: + + A [n,k] linear block code defined by a generator matrix + A [n,k] cyclic code defined by a generator polynomial + A [n,k] Hamming code defined by a primitive polynomial + A [n,k] BCH code code defined by a generator polynomial + + The type of coding to use is defined by the variable TYP. This + variable is a string taking one of the values + + '"linear"' + '"linear/binary"' + A linear block code is assumed with the message MSG being in a + binary format. In this case the argument OPT1 is the + generator matrix, and is required. Additionally, OPT2 + containing the syndrome lookup table (see 'syndtable') can + also be passed + '"cyclic"' + '"cyclic/binary"' + A cyclic code is assumed with the message MSG being in a + binary format. The generator polynomial to use can be defined + in OPT1 The default generator polynomial to use will be + 'cyclpoly (N, K)'. Additionally, OPT2 containing the syndrome + lookup table (see 'syndtable') can also be passed + '"hamming"' + '"hamming/binary"' + A Hamming code is assumed with the message MSG being in a + binary format. In this case N must be of an integer of the + form '2^M-1', where M is an integer. In addition K must be + 'N-M'. The primitive polynomial to use can be defined in + OPT1. The default primitive polynomial to use is the same as + defined by 'hammgen'. The variable OPT2 should not be defined + '"bch"' + '"bch/binary"' + A BCH code is assumed with the message MSG being in a binary + format. The primitive polynomial to use can be defined in + OPT2 The error correction capability of the code can also be + defined in OPT1. Use the empty matrix [] to let the error + correction capability take the default value + + In addition the argument "binary" above can be replaced with + "decimal", in which case the message is assumed to be a decimal + vector, with each value representing a symbol to be coded. The + binary format can be in two forms + + 'An X-by-N matrix' + Each row of this matrix represents a symbol to be decoded + 'A vector with length divisible by N' + The coded symbols are created from groups of N elements of + this vector + + The decoded message is return in MSG. The number of errors + encountered is returned in ERR. If the coded message format is + "decimal" or a "binary" matrix, then ERR is a column vector having + a length equal to the number of decoded symbols. If CODE is a + "binary" vector, then ERR is the same length as MSG and indicated + the number of errors in each symbol. If the value ERR is positive + it indicates the number of errors corrected in the corresponding + symbol. A negative value indicates an uncorrectable error. The + corrected code is returned in CCODE in a similar format to the + coded message MSG. The variable CERR contains similar data to ERR + for CCODE + + It should be noted that all internal calculations are performed in + the binary format. Therefore for large values of N, it is + preferable to use the binary format to pass the messages to avoid + possible rounding errors. Additionally, if repeated calls to + 'decode' will be performed, it is often faster to create a + generator matrix externally with the functions 'hammgen' or + 'cyclgen', rather than let 'decode' recalculate this matrix at each + iteration. In this case TYP should be "linear". The exception to + this case is BCH codes, where the required syndrome table is too + large. The BCH decoder, decodes directly from the polynomial never + explicitly forming the syndrome table + + See also: encode, cyclgen, cyclpoly, hammgen, bchdeco, bchpoly, + syndtable + + +File: comms.info, Node: deconv, Next: deintrlv, Prev: decode, Up: Function Reference + +9.1.25 deconv +------------- + + -- Function File: deconv (Y, A) + Deconvolve two Galois vectors + + '[b, r] = deconv (y, a)' solves for B and R such that 'y = conv (a, + b) + r' + + If Y and A are polynomial coefficient vectors, B will contain the + coefficients of the polynomial quotient and R will be a remainder + polynomial of lowest order See also: conv + + +File: comms.info, Node: deintrlv, Next: demodmap, Prev: deconv, Up: Function Reference + +9.1.26 deintrlv +--------------- + + -- Function File: DEINTRLVD = deintrlv (DATA, ELEMENTS) + Restore elements of DATA according to ELEMENTS See also: intrlv + + +File: comms.info, Node: demodmap, Next: det, Prev: deintrlv, Up: Function Reference + +9.1.27 demodmap +--------------- + + -- Function File: z = demodmap (Y, FD, FS, "ask", M) + -- Function File: z = demodmap (Y, FD, FS, "fsk", M, TONE) + -- Function File: z = demodmap (Y, FD, FS, "msk") + -- Function File: z = demodmap (Y, FD, FS, "psk", M) + -- Function File: z = demodmap (Y, FD, FS, "qask", M) + -- Function File: z = demodmap (Y, FD, FS, "qask/cir", NSIG, AMP, PHS) + -- Function File: z = demodmap (Y, FD, FS, "qask/arb", INPHASE, QUADR) + -- Function File: z = demodmap (Y, FD, FS, "qask/arb", MAP) + -- Function File: z = demodmap (Y, [FD, OFF], ...) + + Demapping of an analog signal to a digital signal. The function + 'demodmap' must have at least three input arguments and one output + argument. Argument Y is a complex variable representing the analog + signal to be demapped. The variables FD and FS are the sampling + rate of the of digital signal and the sampling rate of the analog + signal respectively. It is required that 'FS/FD' is an integer + + The available mapping of the digital signal are + + "ask" + Amplitude shift keying + "fsk" + Frequency shift keying + "msk" + Minimum shift keying + "psk" + Phase shift keying + "qask" + "qsk" + "qam" + Quadrature amplitude shift keying + + In addition the "qask", "qsk" and "qam" method can be modified with + the flags "/cir" or "/arb". That is "qask/cir" and "qask/arb", etc + are valid methods and give circular- and arbitrary-qask mappings + respectively. Also the method "fsk" and "msk" can be modified with + the flag "/max", in which case Y is assumed to be a matrix with M + columns, representing the symbol correlations + + The variable M is the order of the modulation to use. By default + this is 2, and in general should be specified + + For "qask/cir", the additional arguments are the same as for + 'apkconst', and you are referred to 'apkconst' for the definitions + of the additional variables + + For "qask/arb", the additional arguments INPHASE and QUADR give the + in-phase and quadrature components of the mapping, in a similar + mapping to the outputs of 'qaskenco' with one argument. Similar + MAP represents the in-phase and quadrature components of the + mapping as the real and imaginary parts of the variable MAP See + also: modmap, ddemodce, ademodce, apkconst, qaskenco + + +File: comms.info, Node: det, Next: dftmtx, Prev: demodmap, Up: Function Reference + +9.1.28 det +---------- + + -- Loadable Function: D = det (A) + Compute the determinant of the Galois array A + + +File: comms.info, Node: dftmtx, Next: diag, Prev: det, Up: Function Reference + +9.1.29 dftmtx +------------- + + -- Function File: D = dftmtx (A) + + Form a matrix, that can be used to perform Fourier transforms in a + Galois Field + + Given that A is an element of the Galois Field GF(2^m), and that + the minimum value for K for which 'A ^ K' is equal to one is '2^m - + 1', then this function produces a K-by-K matrix representing the + discrete Fourier transform over a Galois Field with respect to A. + The Fourier transform of a column vector is then given by 'dftmtx + (A) * X' + + The inverse Fourier transform is given by 'dftmtx (1 / A)' + + +File: comms.info, Node: diag, Next: dpcmdeco, Prev: dftmtx, Up: Function Reference + +9.1.30 diag +----------- + + -- Loadable Function: diag (V, K) + Return a diagonal matrix with Galois vector V on diagonal K The + second argument is optional. If it is positive, the vector is + placed on the K-th super-diagonal. If it is negative, it is placed + on the -K-th sub-diagonal. The default value of K is 0, and the + vector is placed on the main diagonal. For example, + + diag (gf ([1, 2, 3], 2), 1) + ans = + GF(2^2) array. Primitive Polynomial = D^2+D+1 (decimal 7) + + Array elements = + + 0 1 0 0 + 0 0 2 0 + 0 0 0 3 + 0 0 0 0 + + + +File: comms.info, Node: dpcmdeco, Next: dpcmenco, Prev: diag, Up: Function Reference + +9.1.31 dpcmdeco +--------------- + + -- Function File: SIG = dpcmdeco (INDX, CODEBOOK, PREDICTOR) + Decode using differential pulse code modulation (DPCM) + + 'sig = dpcmdeco (indx, codebook, predictor)' + Decode the signal coded by DPCM Use the prediction model and + the coded prediction error given by a codebook and the index + of each sample in this codebook + + See also: dpcmenco, dpcmopt + + +File: comms.info, Node: dpcmenco, Next: dpcmopt, Prev: dpcmdeco, Up: Function Reference + +9.1.32 dpcmenco +--------------- + + -- Function File: QIDX = dpcmenco (SIG, CODEBOOK, PARTITION, PREDICTOR) + -- Function File: [QIDX, Q] = dpcmenco (SIG, CODEBOOK, PARTITION, + PREDICTOR) + -- Function File: [QIDX, Q, D] = dpcmenco (...) + Encode using differential pulse code modulation (DPCM) + + 'qidx = dpcmenco (sig, codebook, partition, predictor)' + Determine position of the prediction error in a strictly + monotonic table (partition) The predictor vector describes a + m-th order prediction for the output according to the + following equation y(k) = p(1)sig(k-1) + p(2)sig(k-2) + ... + + p(m-1)sig(k-m+1) + p(m)sig(k-m) , where the predictor vector + is given by predictor = [0, p(1), p(2), p(3),..., p(m-1), + p(m)] + + '[qidx, q] = dpcmenco (sig, codebook, partition, predictor)' + Also return the quantized values + + '[qidx, q, d] = dpcmenco (...)' + Also compute distortion: mean squared distance of original sig + from the corresponding quantized values + + See also: dpcmdeco, dpcmopt, quantiz + + +File: comms.info, Node: dpcmopt, Next: egolaydec, Prev: dpcmenco, Up: Function Reference + +9.1.33 dpcmopt +-------------- + + -- Function File: PREDICTOR = dpcmopt (TRAINING_SET, ORD) + -- Function File: [PREDICTOR, PARTITION, CODEBOOK] = dpcmopt + (TRAINING_SET, ORD, CB) + Optimize the DPCM parameters and codebook + + It uses the Levinson-Durbin algorithm to find the all-pole IIR + filter using the autocorrelation sequence. After the best + predictor is found, it uses the Lloyds algorithm to find the best + codebook and partition for the interval + + 'predictor = dpcmopt (training_set, ord)' + Optimize the DPCM parameters using the Levinson-Durbin + algorithm The predictor vector describes a m-th order + prediction for the output according to the following equation + y(k) = p(1)sig(k-1) + p(2)sig(k-2) + ... + p(m-1)sig(k-m+1) + + p(m)sig(k-m) where the predictor vector is given by predictor + = [0, p(1), p(2), p(3),..., p(m-1), p(m)] + + training_set is the training data used to find the best + predictor + + ord is the order of the desired prediction model + + '[predictor, partition, codebook] = dpcmopt (training_set,ord,cb)' + Optimize the DPCM parameters and also uses the Lloyds + algorithm to find the best codebook and partition for the + given training signal + + cb might be the initial codebook used by Lloyds algorithm or + the length of the desired codebook + + See also: dpcmenco, dpcmdeco, levinson, lloyds + + +File: comms.info, Node: egolaydec, Next: egolayenc, Prev: dpcmopt, Up: Function Reference + +9.1.34 egolaydec +---------------- + + -- Function File: [C, ERR] = egolaydec (R) + Decode Extended Golay code + + Given R, the received Extended Golay code, this function tries to + decode it using the Extended Golay code parity check matrix + Extended Golay code (24,12) which can correct up to 3 errors + + The received code R, needs to be of length Nx24, for encoding. We + can decode several codes at once, if they are stacked as a matrix + of 24 columns, each code in a separate row + + The generator used in here is same as obtained from the function + 'egolaygen' + + The function returns C, the error-corrected code word from the + received word. If decoding failed, ERR value is 1, otherwise it is + 0 + + Extended Golay code (24,12) which can correct up to 3 errors. + Decoding algorithm follows from Lin & Costello + + Ref: Lin & Costello, pg 128, Ch4, "Error Control Coding", 2nd ed, + Pearson + + msg = rand (10, 12) > 0.5; + c1 = egolayenc (msg); + c1(:,1) = mod (c1(:,1) + 1, 2) + c2 = egolaydec (c1) + + See also: egolaygen, egolayenc + + +File: comms.info, Node: egolayenc, Next: egolaygen, Prev: egolaydec, Up: Function Reference + +9.1.35 egolayenc +---------------- + + -- Function File: C = egolayenc (M) + Encode with Extended Golay code + + The message M, needs to be of size Nx12, for encoding We can encode + several messages, into codes at once, if they are stacked in the + order suggested + + The generator used in here is same as obtained from the function + 'egolaygen'. Extended Golay code (24,12) which can correct up to 3 + errors + + msg = rand (10, 12) > 0.5; + c = egolayenc (msg) + + See also: egolaygen, egolaydec + + +File: comms.info, Node: egolaygen, Next: encode, Prev: egolayenc, Up: Function Reference + +9.1.36 egolaygen +---------------- + + -- Function File: [G, P] = egolaygen () + Extended Golay code generator matrix + + Returns G, the Extended Golay code (24,12) generator matrix, which + can correct up to 3 errors. P is the parity check matrix, for this + code + + See also: egolaydec, egolayenc + + +File: comms.info, Node: encode, Next: exp, Prev: egolaygen, Up: Function Reference + +9.1.37 encode +------------- + + -- Function File: CODE = encode (MSG, N, K) + -- Function File: CODE = encode (MSG, N, K, TYP) + -- Function File: CODE = encode (MSG, N, K, TYP, OPT) + -- Function File: [CODE, ADDED] = encode (...) + + Top level block encoder. This function makes use of the lower + level functions such as 'cyclpoly', 'cyclgen', 'hammgen', and + 'bchenco'. The message to code is pass in MSG, the codeword length + is N and the message length is K. This function is used to encode + messages using either: + + A [n,k] linear block code defined by a generator matrix + A [n,k] cyclic code defined by a generator polynomial + A [n,k] Hamming code defined by a primitive polynomial + A [n,k] BCH code code defined by a generator polynomial + + The type of coding to use is defined by the variable TYP. This + variable is a string taking one of the values + + '"linear"' + '"linear/binary"' + A linear block code is assumed with the coded message CODE + being in a binary format. In this case the argument OPT is + the generator matrix, and is required + '"cyclic"' + '"cyclic/binary"' + A cyclic code is assumed with the coded message CODE being in + a binary format. The generator polynomial to use can be + defined in OPT The default generator polynomial to use will be + 'cyclpoly (N, K)' + '"hamming"' + '"hamming/binary"' + A Hamming code is assumed with the coded message CODE being in + a binary format. In this case N must be of an integer of the + form '2^M-1', where M is an integer. In addition K must be + 'N-M'. The primitive polynomial to use can be defined in OPT. + The default primitive polynomial to use is the same as defined + by 'hammgen' + '"bch"' + '"bch/binary"' + A BCH code is assumed with the coded message CODE being in a + binary format. The generator polynomial to use can be defined + in OPT The default generator polynomial to use will be + 'bchpoly (N, K)' + + In addition the argument "binary" above can be replaced with + "decimal", in which case the message is assumed to be a decimal + vector, with each value representing a symbol to be coded. The + binary format can be in two forms + + 'An X-by-K matrix' + Each row of this matrix represents a symbol to be coded + 'A vector' + The symbols are created from groups of K elements of this + vector If the vector length is not divisible by K, then zeros + are added and the number of zeros added is returned in ADDED + + It should be noted that all internal calculations are performed in + the binary format. Therefore for large values of N, it is + preferable to use the binary format to pass the messages to avoid + possible rounding errors. Additionally, if repeated calls to + 'encode' will be performed, it is often faster to create a + generator matrix externally with the functions 'hammgen' or + 'cyclgen', rather than let 'encode' recalculate this matrix at each + iteration. In this case TYP should be "linear". The exception to + this case is BCH codes, whose encoder is implemented directly from + the polynomial and is significantly faster + + See also: decode, cyclgen, cyclpoly, hammgen, bchenco, bchpoly + + +File: comms.info, Node: exp, Next: eyediagram, Prev: encode, Up: Function Reference + +9.1.38 exp +---------- + + -- Loadable Function: exp (X) + Compute the anti-logarithm for each element of X for a Galois array + + +File: comms.info, Node: eyediagram, Next: fft, Prev: exp, Up: Function Reference + +9.1.39 eyediagram +----------------- + + -- Function File: eyediagram (X, N) + -- Function File: eyediagram (X, N, PER) + -- Function File: eyediagram (X, N, PER, OFF) + -- Function File: eyediagram (X, N, PER, OFF, STR) + -- Function File: eyediagram (X, N, PER, OFF, STR, H) + -- Function File: H = eyediagram (...) + + Plot the eye-diagram of a signal. The signal X can be either in + one of three forms + + A real vector + In this case the signal is assumed to be real and represented + by the vector X. A single eye-diagram representing this + signal is plotted + A complex vector + In this case the in-phase and quadrature components of the + signal are plotted separately + A matrix with two columns + In this case the first column represents the in-phase and the + second the quadrature components of a complex signal + + Each line of the eye-diagram has N elements and the period is + assumed to be given by PER. The time axis is then [-PER/2 PER/2] + By default PER is 1 + + By default the signal is assumed to start at -PER/2. This can be + overridden by the OFF variable, which gives the number of samples + to delay the signal + + The string STR is a plot style string (example "r+"), and by + default is the default gnuplot line style + + The figure handle to use can be defined by H. If H is not given, + then the next available figure handle is used. The figure handle + used in returned on HOUT See also: scatterplot + + +File: comms.info, Node: fft, Next: fibodeco, Prev: eyediagram, Up: Function Reference + +9.1.40 fft +---------- + + -- Function File: fft (X) + + If X is a column vector, finds the FFT over the primitive element + of the Galois Field of X. If X is in the Galois Field GF(2^M), + then X must have '2^M - 1' elements + + +File: comms.info, Node: fibodeco, Next: fiboenco, Prev: fft, Up: Function Reference + +9.1.41 fibodeco +--------------- + + -- Function File: fibodeco (CODE) + + Returns the decoded Fibonacci value from the binary vectors CODE + Universal codes like Fibonacci codes have a useful synchronization + property, only for 255 maximum value we have designed these + routines. We assume user has partitioned the code into several + unique segments based on the suffix property of unique strings "11" + and we just decode the parts. Partitioning the stream is as simple + as identifying the "11" pairs that occur, at the terminating ends. + This system implements the standard binary Fibonacci codes, which + means that row vectors can only contain 0 or 1. Ref: + + + fibodeco ({[0 1 0 0 1 1]}) + => 10 + fibodeco ({[1 1], [0 1 1], [0 0 1 1], [1 0 1 1]}) + => [1, 2, 3, 4] + See also: fiboenco + + +File: comms.info, Node: fiboenco, Next: fibosplitstream, Prev: fibodeco, Up: Function Reference + +9.1.42 fiboenco +--------------- + + -- Function File: fiboenco (NUM) + + Returns the cell-array of encoded Fibonacci value from the column + vectors NUM Universal codes like Fibonacci codes have a useful + synchronization property, only for 255 maximum value we have + designed these routines. We assume user has partitioned the code + into several unique segments based on the suffix property of unique + elements [1 1] and we just decode the parts. Partitioning the + stream is as simple as identifying the [1 1] pairs that occur, at + the terminating ends. This system implements the standard binary + Fibonacci codes, which means that row vectors can only contain 0 or + 1. Ref: http://en.wikipedia.org/wiki/Fibonacci_coding Ugly + O(k.N^2) encoder.Ref: Wikipedia article accessed March, 2006 + , UCI Data + Compression Book, , + (accessed October 2006) + + fiboenco (10) + => {[ 0 1 0 0 1 1]} + fiboenco (1:4) + => {[1 1], [0 1 1], [0 0 1 1], [1 0 1 1]} + See also: fibodeco + + +File: comms.info, Node: fibosplitstream, Next: filter, Prev: fiboenco, Up: Function Reference + +9.1.43 fibosplitstream +---------------------- + + -- Function File: fibosplitstream (CODE) + + Returns the split data stream at the word boundaries Assuming the + stream was originally encoded using 'fiboenco' and this routine + splits the stream at the points where "11" occur together & gives + us the code-words which can later be decoded from the 'fibodeco' + This however doesn't mean that we intend to verify if all the + codewords are correct, and in fact the last symbol in the return + list can or can not be a valid codeword + + A example use of 'fibosplitstream' would be + fibodeco (fibosplitstream ([fiboenco(randint (1, 100, [0, 255])){:}])) + fibodeco (fibosplitstream ([fiboenco(1:10){:}])) + See also: fiboenco, fibodeco + + +File: comms.info, Node: filter, Next: finddelay, Prev: fibosplitstream, Up: Function Reference + +9.1.44 filter +------------- + + -- Loadable Function: y = filter (B, A, X) + -- Loadable Function: [Y, SF] = filter (B, A, X, SI) + + Digital filtering of vectors in a Galois Field. Returns the + solution to the following linear, time-invariant difference + equation over a Galois Field: + + N M + SUM a(k+1) y(n-k) = SUM b(k+1) x(n-k) for 1<=n<=length(x) + k=0 k=0 + + where N=length(a)-1 and M=length(b)-1 An equivalent form of this + equation is: + + N M + y(n) = - SUM c(k+1) y(n-k) + SUM d(k+1) x(n-k) for 1<=n<=length(x) + k=1 k=0 + + where c = a/a(1) and d = b/a(1) + + If the fourth argument SI is provided, it is taken as the initial + state of the system and the final state is returned as SF. The + state vector is a column vector whose length is equal to the length + of the longest coefficient vector minus one If SI is not supplied, + the initial state vector is set to all zeros + + +File: comms.info, Node: finddelay, Next: fmdemod, Prev: filter, Up: Function Reference + +9.1.45 finddelay +---------------- + + -- Function File: D = finddelay (X, Y) + Estimate the delay between times series X and time series Y by + correlating and finding the peak. The index of the peak + correlation is returned in D + + Inputs: + X, Y: signals + + Output: + D: The delay between the two signals + + Example: + x = [0, 0, 1, 2, 3]; + y = [1, 2, 3]; + d = finddelay (x, y) + d = -2 + See also: xcorr + + +File: comms.info, Node: fmdemod, Next: fmmod, Prev: finddelay, Up: Function Reference + +9.1.46 fmdemod +-------------- + + -- Function File: M = fmdemod (S, FC, FS) + Creates the FM demodulation of the signal S sampled at frequency FS + with carrier frequency FC + + Inputs: + * S: FM modulated signal + + * FC: carrier frequency + + * FS: sampling frequency + + Output: + M: FM demodulation of the signal + + See also: ammod, amdemod, fmmod + + +File: comms.info, Node: fmmod, Next: gen2par, Prev: fmdemod, Up: Function Reference + +9.1.47 fmmod +------------ + + -- Function File: S = fmmod (M, FC, FS, FREQDEV) + Creates the FM modulation S of the message signal M with carrier + frequency FC + + Inputs: + * M: sinusoidal message signal + + * FC: carrier frequency + + * FS: sampling frequency + + * FREQDEV: maximum absolute frequency deviation, assuming M is + in [-1:1] + + Output: + S: The FM modulation of M + + Demo + demo fmmod + See also: ammod, fmdemod, amdemod + + +File: comms.info, Node: gen2par, Next: genqamdemod, Prev: fmmod, Up: Function Reference + +9.1.48 gen2par +-------------- + + -- Function File: PAR = gen2par (GEN) + -- Function File: GEN = gen2par (PAR) + + Converts binary generator matrix GEN to the parity check matrix PAR + and visa-versa. The input matrix must be in standard form That is + a generator matrix must be k-by-n and in the form [eye(k) P] or [P + eye(k)], and the parity matrix must be (n-k)-by-n and of the form + [eye(n-k) P'] or [P' eye(n-k)] + + See also: cyclgen, hammgen + + +File: comms.info, Node: genqamdemod, Next: genqammod, Prev: gen2par, Up: Function Reference + +9.1.49 genqamdemod +------------------ + + -- Loadable Function: Y = genqamdemod (X, C) + General quadrature amplitude demodulation. The complex envelope + quadrature amplitude modulated signal X is demodulated using a + constellation mapping specified by the 1D vector C. + + +File: comms.info, Node: genqammod, Next: gf, Prev: genqamdemod, Up: Function Reference + +9.1.50 genqammod +---------------- + + -- Function File: Y = genqammod (X, C) + + Modulates an information sequence of integers X in the range '[0 + ... M-1]' onto a quadrature amplitude modulated signal Y, where 'M + = length (c) - 1' and C is a 1D vector specifying the signal + constellation mapping to be used. An example of combined 4PAM-4PSK + is + + d = randint (1, 1e4, 8); + c = [1+j -1+j -1-j 1-j 1+sqrt(3) j*(1+sqrt(3)) -1-sqrt(3) -j*(1+sqrt(3))]; + y = genqammod (d, c); + z = awgn (y, 20); + plot (z, "rx") + See also: genqamdemod + + +File: comms.info, Node: gf, Next: gftable, Prev: genqammod, Up: Function Reference + +9.1.51 gf +--------- + +#endif "-*- texinfo -*- \ + + +File: comms.info, Node: gftable, Next: gfweight, Prev: gf, Up: Function Reference + +9.1.52 gftable +-------------- + + -- Function File: gftable (M, PRIMPOLY) + + This function exists for compatibility with matlab. As the Octave + Galois fields store a copy of the lookup tables for every field in + use internally, there is no need to use this function + + See also: gf + + +File: comms.info, Node: gfweight, Next: golombdeco, Prev: gftable, Up: Function Reference + +9.1.53 gfweight +--------------- + + -- Function File: W = gfweight (GEN) + -- Function File: W = gfweight (GEN, "gen") + -- Function File: W = gfweight (PAR, "par") + -- Function File: W = gfweight (P, n) + + Calculate the minimum weight or distance of a linear block code. + The code can be either defined by its generator or parity check + matrix, or its generator polynomial. By default if the first + argument is a matrix, it is assumed to be the generator matrix of + the code. The type of the matrix can be defined by a flag "gen" + for the generator matrix or "par" for the parity check matrix + + If the first argument is a vector, it is assumed that it defines + the generator polynomial of the code. In this case a second + argument is required that defines the codeword length + + See also: hammgen, cyclpoly, bchpoly + + +File: comms.info, Node: golombdeco, Next: golombenco, Prev: gfweight, Up: Function Reference + +9.1.54 golombdeco +----------------- + + -- Function File: golombdeco (CODE, M) + + Returns the Golomb decoded signal vector using CODE and M + Compulsory m is need to be specified. A restrictions is that a + signal set must strictly be non-negative. The value of code is a + cell array of row-vectors which have the encoded Golomb value for a + single sample. The Golomb algorithm is used to encode the "code" + and only that can be meaningfully decoded. CODE is assumed to have + been of format generated by the function 'golombenco'. Also the + parameter M need to be a non-zero number, unless which it makes + divide-by-zero errors This function works backward the Golomb + algorithm see 'golombenco' for more details on that Reference: + Solomon Golomb, Run length Encodings, 1966 IEEE Trans Info Theory + + An example of the use of 'golombdeco' is + golombdeco (golombenco (1:4, 2), 2) + => [1 2 3 4] + See also: golombenco + + +File: comms.info, Node: golombenco, Next: hammgen, Prev: golombdeco, Up: Function Reference + +9.1.55 golombenco +----------------- + + -- Function File: golombenco (SIG, M) + + Returns the Golomb coded signal as cell array Also total length of + output code in bits can be obtained This function uses a M need to + be supplied for encoding signal vector into a Golomb coded vector. + A restrictions is that a signal set must strictly be non-negative. + Also the parameter M need to be a non-zero number, unless which it + makes divide-by-zero errors The Golomb algorithm [1], is used to + encode the data into unary coded quotient part which is represented + as a set of 1's separated from the K-part (binary) using a zero. + This scheme doesn't need any kind of dictionaries, it is a + parameterized prefix codes Implementation is close to O(N^2), but + this implementation *may be* sluggish, though correct. Details of + the scheme are, to encode the remainder(r of number N) using the + floor(log2(m)) bits when rem is in range 0:(2^ceil(log2(m)) - N), + and encode it as r+(2^ceil(log2(m)) - N), using total of + 2^ceil(log2(m)) bits in other instance it doesn't belong to case 1. + Quotient is coded simply just using the unary code. Also according + to [2] Golomb codes are optimal for sequences using the Bernoulli + probability model: P(n)=p^n-1.q & p+q=1, and when M=[1/log2(p)], or + P=2^(1/M) + + Reference: 1. Solomon Golomb, Run length Encodings, 1966 IEEE + Trans Info' Theory. 2. Khalid Sayood, Data Compression, 3rd + Edition + + An example of the use of 'golombenco' is + golombenco (1:4, 2) + => {[0 1], [1 0 0], [1 0 1], [1 1 0 0]} + golombenco (1:10, 2) + => {[0 1], [1 0 0], [1 0 1], [1 1 0 0], + [1 1 0 1], [1 1 1 0 0], [1 1 1 0 1], [1 1 1 1 0 0], + [1 1 1 1 0 1], [1 1 1 1 1 0 0]} + See also: golombdeco + + +File: comms.info, Node: hammgen, Next: helscanintrlv, Prev: golombenco, Up: Function Reference + +9.1.56 hammgen +-------------- + + -- Function File: H = hammgen (M) + -- Function File: H = hammgen (M, P) + -- Function File: [H, G] = hammgen (...) + -- Function File: [H, G, N, K] = hammgen (...) + + Produce the parity check and generator matrices of a Hamming code. + The variable M defines the [N,K] Hamming code where 'N = 2 ^ M - 1' + and 'K = N - M' M must be between 3 and 16 + + The parity check matrix is generated relative to the primitive + polynomial of GF(2^M). If P is specified the default primitive + polynomial of GF(2^M) is overridden. P must be a valid primitive + polynomial of the correct order for GF(2^M) + + The parity check matrix is returned in the M by N matrix H, and if + requested the generator matrix is returned in the K by N matrix G + + See also: gen2par + + +File: comms.info, Node: helscanintrlv, Next: huffmandeco, Prev: hammgen, Up: Function Reference + +9.1.57 helscanintrlv +-------------------- + + -- Function File: OUTDATA = helscanintrlv (DATA, NROWS, NCOLS, NSHIFT) + NROWS-by-NCOLS See also: helscandeintrlv + + +File: comms.info, Node: huffmandeco, Next: huffmandict, Prev: helscanintrlv, Up: Function Reference + +9.1.58 huffmandeco +------------------ + + -- Function File: SIG = huffmandeco (HCODE, DICT) + Decode signal encoded by 'huffmanenco' + + This function uses a dict built from the 'huffmandict' and uses it + to decode a signal list into a Huffman list. A restriction is that + HCODE is expected to be a binary code + + The returned SIG set that strictly belongs in the range '[1,N]' + with 'N = length (DICT)'. Also DICT can only be from the + 'huffmandict' routine. Whenever decoding fails, those signal + values a re indicated by '-1', and we successively try to restart + decoding from the next bit that hasn't failed in decoding, + ad-infinitum. An example of the use of 'huffmandeco' is: + + hd = huffmandict (1:4, [0.5 0.25 0.15 0.10]); + hcode = huffmanenco (1:4, hd); + back = huffmandeco (hcode, hd) + => [1 2 3 4] + See also: huffmandict, huffmanenco + + +File: comms.info, Node: huffmandict, Next: huffmanenco, Prev: huffmandeco, Up: Function Reference + +9.1.59 huffmandict +------------------ + + -- Function File: huffmandict (SYMB, PROB) + -- Function File: huffmandict (SYMB, PROB, TOGGLE) + -- Function File: huffmandict (SYMB, PROB, TOGGLE, MINVAR) + + Builds a Huffman code, given a probability list. The Huffman codes + per symbol are output as a list of strings-per-source symbol. A + zero probability symbol is NOT assigned any codeword as this symbol + doesn't occur in practice anyway + + TOGGLE is an optional argument with values 1 or 0, that starts + building a code based on 1s or 0s, defaulting to 0. Also MINVAR is + a boolean value that is useful in choosing if you want to optimize + buffer for transmission in the applications of Huffman coding, + however it doesn't affect the type or average codeword length of + the generated code. An example of the use of 'huffmandict' is + + huffmandict (symbols, [0.5 0.25 0.15 0.1], 1) + => {[0], [1 0], [1 1 1], [1 1 0]} + huffmandict (symbols, 0.25 * ones (1,4), 1) + => {[1 1], [1 0], [0 1], [0 0]} + + prob = [0.5 0 0.25 0.15 0.1]; + dict = huffmandict (1:5, prob, 1); + entropy (prob) + => 2.3219 + laverage (dict, prob) + => 1.8500 + + x = [0.2 0.4 0.2 0.1 0.1]; + huffmandict (1, x, 0, true) + => {[1 0], [0 0], [1 1], [0 1 0], [0 1 1]} + huffmandict (1, x) + => {[0 1], [1], [0 0 1], [0 0 0 0], [0 0 0 1]} + + Reference: Dr.Rao's course EE5351 Digital Video Coding, at + UT-Arlington See also: huffmandeco, huffmanenco + + +File: comms.info, Node: huffmanenco, Next: ifft, Prev: huffmandict, Up: Function Reference + +9.1.60 huffmanenco +------------------ + + -- Function File: huffmanenco (SIG, DICT) + + Returns the Huffman encoded signal using DICT. This function uses + a DICT built from the 'huffmandict' and uses it to encode a signal + list into a Huffman list. A restrictions is that a signal set must + strictly belong in the range '[1,N]' with 'N = length (dict)' Also + DICT can only be from the 'huffmandict' routine An example of the + use of 'huffmanenco' is + + hd = huffmandict (1:4, [0.5 0.25 0.15 0.10]); + huffmanenco (1:4, hd) + => [1 0 1 0 0 0 0 0 1] + See also: huffmandict, huffmandeco + + +File: comms.info, Node: ifft, Next: intrlv, Prev: huffmanenco, Up: Function Reference + +9.1.61 ifft +----------- + + -- Function File: ifft (X) + + If X is a column vector, finds the IFFT over the primitive element + of the Galois Field of X. If X is in the Galois Field GF(2^M), + then X must have '2^M - 1' elements See also: ifft + + +File: comms.info, Node: intrlv, Next: inv, Prev: ifft, Up: Function Reference + +9.1.62 intrlv +------------- + + -- Function File: INTRLVD = intrlv (DATA, ELEMENTS) + Interleaved elements of DATA according to ELEMENTS See also: + deintrlv + + +File: comms.info, Node: inv, Next: inverse, Prev: intrlv, Up: Function Reference + +9.1.63 inv +---------- + + -- Loadable Function: [X, RCOND] = inv (A) + Compute the inverse of the square matrix A. Return an estimate of + the reciprocal condition number if requested, otherwise warn of an + ill-conditioned matrix if the reciprocal condition number is small + + +File: comms.info, Node: inverse, Next: isequal, Prev: inv, Up: Function Reference + +9.1.64 inverse +-------------- + + -- Loadable Function: [X, RCOND] = inverse (A) + See inv + + +File: comms.info, Node: isequal, Next: isgalois, Prev: inverse, Up: Function Reference + +9.1.65 isequal +-------------- + + -- Function File: isequal (X1, X2, ...) + Return true if all of X1, X2, ... are equal See also: + isequalwithequalnans + + +File: comms.info, Node: isgalois, Next: isprimitive, Prev: isequal, Up: Function Reference + +9.1.66 isgalois +--------------- + + -- Loadable Function: isgalois (EXPR) + Return 1 if the value of the expression EXPR is a Galois Field. + + +File: comms.info, Node: isprimitive, Next: istrellis, Prev: isgalois, Up: Function Reference + +9.1.67 isprimitive +------------------ + + -- Loadable Function: Y = isprimitive (A) + Returns 1 is the polynomial represented by A is a primitive + polynomial of GF(2). Otherwise it returns zero. + + See also: gf, primpoly + + +File: comms.info, Node: istrellis, Next: lloyds, Prev: isprimitive, Up: Function Reference + +9.1.68 istrellis +---------------- + + -- Function File: istrellis (T) + -- Function File: [STATUS, TEXT] = istrellis (T) + + Return true if T is a valid trellis structure + + If called with two output arguments, TEXT contains a string + indicating a reason if STATUS is false or an empty string if STATUS + is true + + See also: poly2trellis, struct + + +File: comms.info, Node: lloyds, Next: log, Prev: istrellis, Up: Function Reference + +9.1.69 lloyds +------------- + + -- Function File: [TABLE, CODES] = lloyds (SIG, INIT_CODES) + -- Function File: [TABLE, CODES] = lloyds (SIG, LEN) + -- Function File: [TABLE, CODES] = lloyds (SIG, ..., TOL) + -- Function File: [TABLE, CODES] = lloyds (SIG, ..., TOL, TYPE) + -- Function File: [TABLE, CODES, DIST] = lloyds (...) + -- Function File: [TABLE, CODES, DIST, RELDIST] = lloyds (...) + + Optimize the quantization table and codes to reduce distortion. + This is based on the article by Lloyd + + S. Lloyd _Least squared quantization in PCM_, IEEE Trans Inform + Theory, Mar 1982, no 2, p129-137 + + which describes an iterative technique to reduce the quantization + error by making the intervals of the table such that each interval + has the same area under the PDF of the training signal SIG. The + initial codes to try can either be given in the vector INIT_CODES + or as scalar LEN. In the case of a scalar the initial codes will + be an equi-spaced vector of length LEN between the minimum and + maximum value of the training signal + + The stopping criteria of the iterative algorithm is given by + + abs(DIST(n) - DIST(n-1)) < max(TOL, abs(EPS*max(SIG)) + + By default TOL is 1.e-7. The final input argument determines how + the updated table is created. By default the centroid of the + values of the training signal that fall within the interval + described by CODES are used to update TABLE. If TYPE is any other + string than "centroid", this behavior is overridden and TABLE is + updated as follows + + TABLE = (CODE(2:length(CODE)) + CODE(1:length(CODE-1))) / 2 + + The optimized values are returned as TABLE and CODE. In addition + the distortion of the optimized codes representing the training + signal is returned as DIST. The relative distortion in the final + iteration is also returned as RELDIST + + See also: quantiz + + +File: comms.info, Node: log, Next: lu, Prev: lloyds, Up: Function Reference + +9.1.70 log +---------- + + -- Loadable Function: log (X) + Compute the natural logarithm for each element of X for a Galois + array + + +File: comms.info, Node: lu, Next: lz77deco, Prev: log, Up: Function Reference + +9.1.71 lu +--------- + + -- Loadable Function: [L, U, P] = lu (A) + Compute the LU decomposition of A in a Galois Field. The result is + returned in a permuted form, according to the optional return value + P. For example, given the matrix 'a = gf ([1, 2; 3, 4], 3)', + + [l, u, p] = lu (a) + + returns + + l = + GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + + Array elements = + + 1 0 + 6 1 + + u = + GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + + Array elements = + + 3 4 + 0 7 + + p = + + Permutation Matrix + + 0 1 + 1 0 + + + Such that 'P * A = L * U'. If the argument P is not included then + the permutations are applied to L so that 'A = L * U'. L is then a + pseudo- lower triangular matrix. The matrix A can be rectangular + + +File: comms.info, Node: lz77deco, Next: lz77enco, Prev: lu, Up: Function Reference + +9.1.72 lz77deco +--------------- + + -- Function File: M = lz77deco (C, ALPH, LA, N) + Lempel-Ziv 77 source algorithm decoding implementation. Where + + M + message decoded (1xN) + C + encoded message (Mx3) + ALPH + size of alphabet + LA + lookahead buffer size + N + sliding window buffer size + See also: lz77enco + + +File: comms.info, Node: lz77enco, Next: matdeintrlv, Prev: lz77deco, Up: Function Reference + +9.1.73 lz77enco +--------------- + + -- Function File: C = lz77enco (M, ALPH, LA, N) + Lempel-Ziv 77 source algorithm implementation. Where + + C + encoded message (Mx3) + ALPH + size of alphabet + LA + lookahead buffer size + N + sliding window buffer size + See also: lz77deco + + +File: comms.info, Node: matdeintrlv, Next: matintrlv, Prev: lz77enco, Up: Function Reference + +9.1.74 matdeintrlv +------------------ + + -- Function File: INTRLVD = matdeintrlv (DATA, NROWS, NCOLS) + Restore elements of DATA with a temporary matrix of size + NROWS-by-NCOLS See also: matintrlv + + +File: comms.info, Node: matintrlv, Next: minpol, Prev: matdeintrlv, Up: Function Reference + +9.1.75 matintrlv +---------------- + + -- Function File: INTRLVD = matintrlv (DATA, NROWS, NCOLS) + Interleaved elements of DATA with a temporary matrix of size + NROWS-by-NCOLS See also: matdeintrlv + + +File: comms.info, Node: minpol, Next: modmap, Prev: matintrlv, Up: Function Reference + +9.1.76 minpol +------------- + + -- Function File: minpol (V) + + Finds the minimum polynomial for elements of a Galois Field. For a + vector V with N components, representing N values in a Galois Field + GF(2^M), return the minimum polynomial in GF(2) representing those + values + + +File: comms.info, Node: modmap, Next: oct2dec, Prev: minpol, Up: Function Reference + +9.1.77 modmap +------------- + + -- Function File: modmap (METHOD, ...) + -- Function File: y = modmap (X, FD, FS, "ask", M) + -- Function File: y = modmap (X, FD, FS, "fsk", M, TONE) + -- Function File: y = modmap (X, FD, FS, "msk") + -- Function File: y = modmap (X, FD, FS, "psk", M) + -- Function File: y = modmap (X, FD, FS, "qask", M) + -- Function File: y = modmap (X, FD, FS, "qask/cir", NSIG, AMP, PHS) + -- Function File: y = modmap (X, FD, FS, "qask/arb", INPHASE, QUADR) + -- Function File: y = modmap (X, FD, FS, "qask/arb", MAP) + + Mapping of a digital signal to an analog signal. With no output + arguments 'modmap' plots the constellation of the mapping. In this + case the first argument must be the string METHOD defining one of + "ask", "fsk", "msk", "qask", "qask/cir" or "qask/arb". The + arguments following the string METHOD are generally the same as + those after the corresponding string in the function call without + output arguments The exception is 'modmap ("msk", FD)' + + With an output argument, Y is the complex mapped analog signal. In + this case the arguments X, FD and FS are required. The variable X + is the digital signal to be mapped, FD is the sampling rate of the + of digital signal and the FS is the sampling rate of the analog + signal. It is required that 'FS/FD' is an integer + + The available mapping of the digital signal are + + "ask" + Amplitude shift keying + "fsk" + Frequency shift keying + "msk" + Minimum shift keying + "psk" + Phase shift keying + "qask" + "qsk" + "qam" + Quadrature amplitude shift keying + + In addition the "qask", "qsk" and "qam" method can be modified with + the flags "/cir" or "/arb". That is "qask/cir" and "qask/arb", etc + are valid methods and give circular- and arbitrary-qask mappings + respectively + + The additional argument M is the order of the modulation to use M + must be larger than the largest element of X. The variable TONE is + the FSK tone to use in the modulation + + For "qask/cir", the additional arguments are the same as for + 'apkconst', and you are referred to 'apkconst' for the definitions + of the additional variables + + For "qask/arb", the additional arguments INPHASE and QUADR give the + in-phase and quadrature components of the mapping, in a similar + mapping to the outputs of 'qaskenco' with one argument. Similar + MAP represents the in-phase and quadrature components of the + mapping as the real and imaginary parts of the variable MAP See + also: demodmap, dmodce, amodce, apkconst, qaskenco + + +File: comms.info, Node: oct2dec, Next: pamdemod, Prev: modmap, Up: Function Reference + +9.1.78 oct2dec +-------------- + + -- Function File: D = oct2dec (C) + + Convert octal to decimal values + + Each element of the octal matrix C is converted to a decimal value + + See also: base2dec, bin2dec, dec2bin + + +File: comms.info, Node: pamdemod, Next: pammod, Prev: oct2dec, Up: Function Reference + +9.1.79 pamdemod +--------------- + + -- Function File: Y = pamdemod (X, M) + -- Function File: Y = pamdemod (X, M, PHI) + -- Function File: Y = pamdemod (X, M, PHI, TYPE) + + Demodulates a pulse amplitude modulated signal X into an + information sequence of integers in the range '[0 ... M-1]' PHI + controls the initial phase and TYPE controls the constellation + mapping. If TYPE is set to "Bin" will result in binary encoding, + in contrast, if set to "Gray" will give Gray encoding An example of + Gray-encoded 8-PAM is + + d = randint (1, 1e4, 8); + y = pammod (d, 8, 0, "gray"); + z = awgn (y, 20); + d_est = pamdemod (z, 8, 0, "gray"); + plot (z, "rx") + biterr (d, d_est) + See also: pammod + + +File: comms.info, Node: pammod, Next: poly2trellis, Prev: pamdemod, Up: Function Reference + +9.1.80 pammod +------------- + + -- Function File: Y = pammod (X, M) + -- Function File: Y = pammod (X, M, PHI) + -- Function File: Y = pammod (X, M, PHI, TYPE) + + Modulates an information sequence of integers X in the range '[0 + ... M-1]' onto a pulse amplitude modulated signal Y PHI controls + the initial phase and TYPE controls the constellation mapping. If + TYPE is set to "Bin" will result in binary encoding, in contrast, + if set to "Gray" will give Gray encoding An example of Gray-encoded + 8-PAM is + + d = randint (1, 1e4, 8); + y = pammod (d, 8, 0, "gray"); + z = awgn (y, 20); + plot (z, "rx") + See also: pamdemod + + +File: comms.info, Node: poly2trellis, Next: primpoly, Prev: pammod, Up: Function Reference + +9.1.81 poly2trellis +------------------- + + -- Function File: T = poly2trellis (M, G) + + Convert convolutional code generator polynomials into trellis form + + The arguments M and G together describe a rate k/n feedforward + convolutional encoder. The optional argument F adds feedback + support The output T is a trellis structure describing the same + encoder with the fields listed below + + The vector M is a k-by-1 array containing the lengths of each of + the shift registers for the k input bits to the encoder + + The matrix G is a k-by-n octal-value matrix describing the + generation of each of the n outputs from each of the k inputs. For + a particular entry of G, the least-significant bit corresponds to + the most-delayed input bit in the kth shift-register + + The optional vector F is a 1-by-k vector of octal numbers + describing the feedback of each of the shift registers + + The returned trellis structure contains the following fields: + + 'numInputSymbols' + The number of k-bit input symbols possible, i.e. 2^k + + 'numOutputSymbols' + The number of n-bit output symbols possible, i.e. 2^n + + 'numStates' + The number of states in the trellis + + 'nextStates' + The state transition table for the trellis. The ith row + contains the indices of the states reachable from the (i-1)th + state for each possible input symbol + + 'outputs' + A table of octal-encoded output values for the trellis. The + ith row contains values representing the output symbols + produced in the (i-1)th state for each possible input symbol + + Input symbols, output symbols, and encoder states are all + interpreted with the lowest indices being the most significant bits + + References: + + [1] S. Lin and D. J. Costello, "Convolutional codes," in 'Error + Control Coding', 2nd ed. Upper Saddle River, NJ: Pearson, 2004, + ch. 11, pp. 453-513 + + See also: istrellis + + +File: comms.info, Node: primpoly, Next: prod, Prev: poly2trellis, Up: Function Reference + +9.1.82 primpoly +--------------- + + -- Loadable Function: Y = primpoly (M) + -- Loadable Function: Y = primpoly (M, OPT) + -- Loadable Function: Y = primpoly (..., "nodisplay\") + Finds the primitive polynomials in GF(2^M). + + The first form of this function returns the default primitive + polynomial of GF(2^M). This is the minimum primitive polynomial of + the field. The polynomial representation is printed and an integer + representation of the polynomial is returned + + The call 'primpoly (M, OPT)' returns one or more primitive + polynomials. The output of the function is dependent of the value + of OPT. Valid values of OPT are: + + '\"all\"' + Returns all of the primitive polynomials of GF(2^M) + '\"min\"' + Returns the minimum primitive polynomial of GF(2^M) + '\"max\"' + Returns the maximum primitive polynomial of GF(2^M) + K + Returns the primitive polynomials having exactly K non-zero + terms + + The call 'primpoly (..., \"nodisplay\")' disables the output of the + polynomial forms of the primitives. The return value is not + affected. + + See also: gf, isprimitive + + +File: comms.info, Node: prod, Next: pskdemod, Prev: primpoly, Up: Function Reference + +9.1.83 prod +----------- + + -- Loadable Function: prod (X, DIM) + Product of elements along dimension DIM of Galois array. If DIM is + omitted, it defaults to 1 (column-wise products) + + +File: comms.info, Node: pskdemod, Next: pskmod, Prev: prod, Up: Function Reference + +9.1.84 pskdemod +--------------- + + -- Function File: Y = pamdemod (X, M) + -- Function File: Y = pamdemod (X, M, PHI) + -- Function File: Y = pamdemod (X, M, PHI, TYPE) + + Demodulates a complex-baseband phase shift keying modulated signal + into an information sequence of integers in the range '[0 ... + M-1]'. PHI controls the initial phase and TYPE controls the + constellation mapping. If TYPE is set to "Bin" will result in + binary encoding, in contrast, if set to "Gray" will give Gray + encoding. An example of Gray-encoded 8-PSK is + + d = randint (1, 1e3, 8); + y = pskmod (d, 8, 0, "gray"); + z = awgn (y, 20); + d_est = pskdemod (z, 8, 0, "gray"); + plot (z, "rx") + biterr (d, d_est) + See also: pskmod + + +File: comms.info, Node: pskmod, Next: qamdemod, Prev: pskdemod, Up: Function Reference + +9.1.85 pskmod +------------- + + -- Function File: Y = pskmod (X, M) + -- Function File: Y = pskmod (X, M, PHI) + -- Function File: Y = pskmod (X, M, PHI, TYPE) + + Modulates an information sequence of integers X in the range '[0 + ... M-1]' onto a complex baseband phase shift keying modulated + signal Y. PHI controls the initial phase and TYPE controls the + constellation mapping. If TYPE is set to "Bin" will result in + binary encoding, in contrast, if set to "Gray" will give Gray + encoding. An example of Gray-encoded QPSK is + + d = randint (1, 5e3, 4); + y = pskmod (d, 4, 0, "gray"); + z = awgn (y, 30); + plot (z, "rx") + See also: pskdemod + + +File: comms.info, Node: qamdemod, Next: qammod, Prev: pskmod, Up: Function Reference + +9.1.86 qamdemod +--------------- + + -- Function File: qamdemod (X, M) + Create the QAM demodulation of x with a size of alphabet m See + also: qammod, pskmod, pskdemod + + +File: comms.info, Node: qammod, Next: qaskdeco, Prev: qamdemod, Up: Function Reference + +9.1.87 qammod +------------- + + -- Function File: qammod (X, M) + Create the QAM modulation of x with a size of alphabet m See also: + qamdemod, pskmod, pskdemod + + +File: comms.info, Node: qaskdeco, Next: qaskenco, Prev: qammod, Up: Function Reference + +9.1.88 qaskdeco +--------------- + + -- Function File: MSG = qaskdeco (C, M) + -- Function File: MSG = qaskdeco (INPHASE, QUADR, M) + -- Function File: MSG = qaskdeco (..., MNMX) + + Demaps an analog signal using a square QASK constellation. The + input signal maybe either a complex variable C, or as two real + variables INPHASE and QUADR representing the in-phase and + quadrature components of the signal + + The argument M must be a positive integer power of 2. By default + the same constellation as created in 'qaskenco' is used by + 'qaskdeco' If is possible to change the values of the minimum and + maximum of the in-phase and quadrature components of the + constellation to account for linear changes in the signal values in + the received signal. The variable MNMX is a 2-by-2 matrix of the + following form + + | min in-phase , max in-phase | + | min quadrature , max quadrature | + + If 'sqrt (M)' is an integer, then 'qaskenco' uses a Gray mapping. + Otherwise, an attempt is made to create a nearly square mapping + with a minimum Hamming distance between adjacent constellation + points See also: qaskenco + + +File: comms.info, Node: qaskenco, Next: qfunc, Prev: qaskdeco, Up: Function Reference + +9.1.89 qaskenco +--------------- + + -- Function File: qaskenco (M) + -- Function File: qaskenco (MSG, M) + -- Function File: Y = qaskenco (...) + -- Function File: [INPHASE, QUADR] = qaskenco (...) + + Map a digital signal using a square QASK constellation. The + argument M must be a positive integer power of 2. With two input + arguments the variable MSG represents the message to be encoded. + The values of MSG must be between 0 and 'M-1'. In all cases + 'qaskenco (M)' is equivalent to 'qaskenco (1:M, M)' + + Three types of outputs can be created depending on the number of + output arguments. That is + + No output arguments + In this case 'qaskenco' plots the constellation. Only the + points in MSG are plotted, which in the case of a single input + argument is all constellation points + A single output argument + The returned variable is a complex variable representing the + in-phase and quadrature components of the mapped message MSG. + With, a single input argument this effectively gives the + mapping from symbols to constellation points + Two output arguments + This is the same as one output argument, expect that the + in-phase and quadrature components are returned explicitly. + That is + + c = qaskenco (msg, m); + [a, b] = qaskenco (msg, m); + all (c == a + 1i*b) + => 1 + + If 'sqrt (M)' is an integer, then 'qaskenco' uses a Gray mapping. + Otherwise, an attempt is made to create a nearly square mapping + with a minimum Hamming distance between adjacent constellation + points See also: qaskdeco + + +File: comms.info, Node: qfunc, Next: qfuncinv, Prev: qaskenco, Up: Function Reference + +9.1.90 qfunc +------------ + + -- Function File: Y = qfunc (X) + Compute the Q function See also: erfc, erf + + +File: comms.info, Node: qfuncinv, Next: quantiz, Prev: qfunc, Up: Function Reference + +9.1.91 qfuncinv +--------------- + + -- Function File: Y = qfuncinv (X) + Compute the inverse Q function See also: erfc, erf + + +File: comms.info, Node: quantiz, Next: randdeintrlv, Prev: qfuncinv, Up: Function Reference + +9.1.92 quantiz +-------------- + + -- Function File: QIDX = quantiz (X, TABLE) + -- Function File: [QIDX, Q] = quantiz (X, TABLE, CODES) + -- Function File: [ QIDX, Q, D] = quantiz (...) + + Quantization of an arbitrary signal relative to a partitioning + + 'qidx = quantiz (x, table)' + Determine position of x in strictly monotonic table. The + first interval, using index 0, corresponds to x <= table(1) + Subsequent intervals are table(i-1) < x <= table(i) + + '[qidx, q] = quantiz (x, table, codes)' + Associate each interval of the table with a code. Use + codes(1) for x <= table(1) and codes(n+1) for table(n) < x <= + table(n+1) + + '[qidx, q, d] = quantiz (...)' + Compute distortion as mean squared distance of x from the + corresponding quantization values + + +File: comms.info, Node: randdeintrlv, Next: randerr, Prev: quantiz, Up: Function Reference + +9.1.93 randdeintrlv +------------------- + + -- Function File: INTRLVD = randdeintrlv (DATA, STATE) + Restore elements of DATA with a random permutation See also: + randintrlv, intrlv, deintrlv + + +File: comms.info, Node: randerr, Next: randint, Prev: randdeintrlv, Up: Function Reference + +9.1.94 randerr +-------------- + + -- Function File: B = randerr (N) + -- Function File: B = randerr (N, M) + -- Function File: B = randerr (N, M, ERR) + -- Function File: B = randerr (N, M, ERR, SEED) + + Generate a matrix of random bit errors. The size of the matrix is + N rows by M columns. By default M is equal to N Bit errors in the + matrix are indicated by a 1 + + The variable ERR determines the number of errors per row. By + default the return matrix B has exactly one bit error per row If + ERR is a scalar, there each row of B has exactly this number of + errors per row. If ERR is a vector then each row has a number of + errors that is in this vector. Each number of errors has an equal + probability. If ERR is a matrix with two rows, then the first row + determines the number of errors and the second their probabilities + + The variable SEED allows the random number generator to be seeded + with a fixed value. The initial seed will be restored when + returning + + +File: comms.info, Node: randint, Next: randintrlv, Prev: randerr, Up: Function Reference + +9.1.95 randint +-------------- + + -- Function File: B = randint (N) + -- Function File: B = randint (N, M) + -- Function File: B = randint (N, M, RANGE) + -- Function File: B = randint (N, M, RANGE, SEED) + + Generate a matrix of random binary numbers. The size of the matrix + is N rows by M columns. By default M is equal to N + + The range in which the integers are generated will is determined by + the variable RANGE. If RANGE is an integer, the value will lie in + the range [0,RANGE-1], or [RANGE+1,0] if RANGE is negative. If + RANGE contains two elements the integers will lie within these two + elements, inclusive. By default RANGE is assumed to be [0:1] + + The variable SEED allows the random number generator to be seeded + with a fixed value. The initial seed will be restored when + returning + + +File: comms.info, Node: randintrlv, Next: randsrc, Prev: randint, Up: Function Reference + +9.1.96 randintrlv +----------------- + + -- Function File: INTRLVD = randintrlv (DATA, STATE) + Interleaves elements of DATA with a random permutation See also: + intrlv, deintrlv + + +File: comms.info, Node: randsrc, Next: rank, Prev: randintrlv, Up: Function Reference + +9.1.97 randsrc +-------------- + + -- Function File: B = randsrc (N) + -- Function File: B = randsrc (N, M) + -- Function File: B = randsrc (N, M, ALPHABET) + -- Function File: B = randsrc (N, M, ALPHABET, SEED) + + Generate a matrix of random symbols. The size of the matrix is N + rows by M columns. By default M is equal to N + + The variable ALPHABET can be either a row vector or a matrix with + two rows. When ALPHABET is a row vector the symbols returned in B + are chosen with equal probability from ALPHABET. When ALPHABET has + two rows, the second row determines the probability with which each + of the symbols is chosen. The sum of the probabilities must equal + 1. By default ALPHABET is [-1 1] + + The variable SEED allows the random number generator to be seeded + with a fixed value. The initial seed will be restored when + returning + + +File: comms.info, Node: rank, Next: rcosfir, Prev: randsrc, Up: Function Reference + +9.1.98 rank +----------- + + -- Loadable Function: D = rank (A) + Compute the rank of the Galois array A by counting the independent + rows and columns + + +File: comms.info, Node: rcosfir, Next: reedmullerdec, Prev: rank, Up: Function Reference + +9.1.99 rcosfir +-------------- + + -- Function File: H, ST = rcosfir(R,NT,RATE,T,FILTERTYPE) + + Implements a cosine filter or root cosine filter impulse response + + R Roll-off factor + + NT scalar vector of length 2 such as N = (nT(2)-nT(1))*rate+1 + + T symbol rate + + FILTERTYPE 'normal' or 'sqrt' + + H impulse response + + ST sampling interval + + Example: + + h = rcosfir(0.2,[-3 3],4,1,'sqrt'); See also: filter, downsample, + rectfilt + + +File: comms.info, Node: reedmullerdec, Next: reedmullerenc, Prev: rcosfir, Up: Function Reference + +9.1.100 reedmullerdec +--------------------- + + -- Function File: reedmullerdec (VV, G, R, M) + + Decode the received code word VV using the RM-generator matrix G, + of order R, M, returning the code-word C. We use the standard + majority logic vote method due to Irving S. Reed. The received + word has to be a matrix of column size equal to to code-word size + (i.e 2^m). Each row is treated as a separate received word + + The second return value is the message M got from C + + G is obtained from definition type construction of Reed-Muller + code, of order R, length 2^M. Use the function reedmullergen, for + the generator matrix for the (R,M) order RM code + + Faster code constructions (also easier) exist, but since finding + permutation order of the basis vectors, is important, we stick with + the standard definitions. To use decoder function reedmullerdec, + you need to use this specific generator function + + see: Lin & Costello, Ch.4, "Error Control Coding", 2nd Ed, Pearson + + g = reedmullergen (2, 4); + msg = rand (1, 11) > 0.5; + c = mod (msg * g, 2); + [dec_c, dec_m] = reedmullerdec (c, g, 2, 4) + See also: reedmullergen, reedmullerenc + + +File: comms.info, Node: reedmullerenc, Next: reedmullergen, Prev: reedmullerdec, Up: Function Reference + +9.1.101 reedmullerenc +--------------------- + + -- Function File: reedmullerenc (MSG, R, M) + + Definition type construction of Reed-Muller code, of order R, + length 2^M. This function returns the generator matrix for the said + order RM code + + Encodes the given message word/block, of column size k, + corresponding to the RM(R,M), and outputs a code matrix C, on each + row with corresponding codeword The second return value is the G, + which is generator matrix used for this code + + msg = rand (10, 11) > 0.5; + [c, g] = reedmullerenc (msg, 2, 4); + See also: reedmullerdec, reedmullergen + + +File: comms.info, Node: reedmullergen, Next: reshape, Prev: reedmullerenc, Up: Function Reference + +9.1.102 reedmullergen +--------------------- + + -- Function File: reedmullergen (R, M) + + Definition type construction of Reed-Muller code, of order R, + length 2^M. This function returns the generator matrix for the said + order RM code + + RM(r,m) codes are characterized by codewords, 'sum ( (m,0) + (m,1) + + ... + (m,r)' Each of the codeword is got through spanning the + space, using the finite set of m-basis codewords Each codeword is + 2^M elements long see: Lin & Costello, "Error Control Coding", 2nd + Ed + + Faster code constructions (also easier) exist, but since finding + permutation order of the basis vectors, is important, we stick with + the standard definitions. To use decoder function reedmullerdec, + you need to use this specific generator function + + g = reedmullergen (2, 4); + See also: reedmullerdec, reedmullerenc + + +File: comms.info, Node: reshape, Next: ricedeco, Prev: reedmullergen, Up: Function Reference + +9.1.103 reshape +--------------- + + -- Loadable Function: reshape (A, M, N) + Return a matrix with M rows and N columns whose elements are taken + from the Galois array A. To decide how to order the elements, + Octave pretends that the elements of a matrix are stored in + column-major order (like Fortran arrays are stored) + + For example, + + reshape (gf ([1, 2, 3, 4], 3), 2, 2) + ans = + GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + + Array elements = + + 1 3 + 2 4 + + + The 'reshape' function is equivalent to + + retval = gf (zeros (m, n), a.m, a.prim_poly); + retval(:) = a; + + but it is somewhat less cryptic to use 'reshape' instead of the + colon operator. Note that the total number of elements in the + original matrix must match the total number of elements in the new + matrix See also: : + + +File: comms.info, Node: ricedeco, Next: riceenco, Prev: reshape, Up: Function Reference + +9.1.104 ricedeco +---------------- + + -- Function File: ricedeco (CODE, K) + + Returns the Rice decoded signal vector using CODE and K Compulsory + K is need to be specified A restrictions is that a signal set must + strictly be non-negative The value of code is a cell array of + row-vectors which have the encoded rice value for a single sample. + The Rice algorithm is used to encode the "code" and only that can + be meaningfully decoded. CODE is assumed to have been of format + generated by the function 'riceenco' + + Reference: Solomon Golomb, Run length Encodings, 1966 IEEE Trans + Info Theory + + An example of the use of 'ricedeco' is + ricedeco (riceenco (1:4, 2), 2) + => [1 2 3 4] + See also: riceenco + + +File: comms.info, Node: riceenco, Next: rledeco, Prev: ricedeco, Up: Function Reference + +9.1.105 riceenco +---------------- + + -- Function File: riceenco (SIG, K) + + Returns the Rice encoded signal using K or optimal K Default + optimal K is chosen between 0-7. Currently no other way to + increase the range except to specify explicitly. Also returns K + parameter used (in case it were to be chosen optimally) and LTOT + the total length of output code in bits This function uses a K if + supplied or by default chooses the optimal K for encoding signal + vector into a rice coded vector A restrictions is that a signal set + must strictly be non-negative The Rice algorithm is used to encode + the data into unary coded quotient part which is represented as a + set of 1's separated from the K-part (binary) using a zero. This + scheme doesn't need any kind of dictionaries and its close to O(N), + but this implementation *may be* sluggish, though correct + + Reference: Solomon Golomb, Run length Encodings, 1966 IEEE Trans + Info' Theory + + An example of the use of 'riceenco' is + riceenco (1:4) + => {[0 1], [1 0 0], [1 0 1], [1 1 0 0]} + riceenco (1:10, 2) + => {[0 0 1], [0 1 0], [0 1 1], [1 0 0 0], + [1 0 0 1], [1 0 1 0], [1 0 1 1], [1 1 0 0 0], + [1 1 0 0 1], [1 1 0 1 0]} + See also: ricedeco + + +File: comms.info, Node: rledeco, Next: rleenco, Prev: riceenco, Up: Function Reference + +9.1.106 rledeco +--------------- + + -- Function File: rledeco (MESSAGE) + + Returns decoded run-length MESSAGE. The RLE encoded MESSAGE has to + be in the form of a row-vector. The message format (encoded RLE) + is like repetition [factor, value]+ + + An example use of 'rledeco' is + message = [1 5 2 4 3 1]; + rledeco (message) + => [5 4 4 1 1 1] + See also: rledeco + + +File: comms.info, Node: rleenco, Next: roots, Prev: rledeco, Up: Function Reference + +9.1.107 rleenco +--------------- + + -- Function File: rleenco (MESSAGE) + + Returns run-length encoded MESSAGE. The RLE form is built from + MESSAGE. The original MESSAGE has to be in the form of a + row-vector. The encoded MESSAGE format (encoded RLE) is like + [repetition factor]+, values + + An example use of 'rleenco' is + message = [5 4 4 1 1 1] + rleenco (message) + => [1 5 2 4 3 1]; + See also: rleenco + + +File: comms.info, Node: roots, Next: rsdec, Prev: rleenco, Up: Function Reference + +9.1.108 roots +------------- + + -- Function File: roots (V) + + For a vector V with N components, return the roots of the + polynomial over a Galois Field + + v(1) * z^(N-1) + ... + v(N-1) * z + v(N) + + The number of roots returned and their value will be determined by + the order and primitive polynomial of the Galois Field + + +File: comms.info, Node: rsdec, Next: rsdecof, Prev: roots, Up: Function Reference + +9.1.109 rsdec +------------- + + -- Loadable Function: MSG = rsdec (CODE, N, K) + -- Loadable Function: MSG = rsdec (CODE, N, K, G) + -- Loadable Function: MSG = rsdec (CODE, N, K, FCR, PRIM) + -- Loadable Function: MSG = rsdec (..., PARPOS) + -- Loadable Function: [MSG, NERR] = rsdec (...) + -- Loadable Function: [MSG, NERR, CCODE] = rsdec (...) + Decodes the message contained in CODE using a [N,K] Reed-Solomon + code. The variable CODE must be a Galois array with N columns and + an arbitrary number of rows. Each row of CODE represents a single + block to be decoded by the Reed-Solomon coder. The decoded message + is returned in the variable MSG containing K columns and the same + number of rows as CODE. + + If N does not equal '2^M-1', where m is an integer, then a shorten + Reed-Solomon decoding is used where zeros are added to the start of + each row to obtain an allowable codeword length. The returned MSG + has these prepending zeros stripped. + + By default the generator polynomial used in the Reed-Solomon coding + is based on the properties of the Galois Field in which MSG is + given. This default generator polynomial can be overridden by a + polynomial in G. Suitable generator polynomials can be constructed + with 'rsgenpoly'. FCR is an integer value, and it is taken to be + the first consecutive root of the generator polynomial. The + variable PRIM is then the primitive element used to construct the + generator polynomial. By default FCR and PRIM are both 1. It is + significantly faster to specify the generator polynomial in terms + of FCR and PRIM, since G is converted to this form in any case. + + By default the parity symbols are placed at the end of the coded + message. The variable PARPOS controls this positioning and can + take the values '"beginning\"' or '\"end\"'. If the parity symbols + are at the end, the message is treated with the most-significant + symbol first, otherwise the message is treated with the + least-significant symbol first. See also: gf, rsenc, rsgenpoly + + +File: comms.info, Node: rsdecof, Next: rsenc, Prev: rsdec, Up: Function Reference + +9.1.110 rsdecof +--------------- + + -- Function File: rsdecof (IN, OUT) + -- Function File: rsdecof (IN, OUT, T) + + Decodes an ASCII file using a Reed-Solomon coder. The input file + is defined by IN and the result is written to the output file OUT + The type of coding to use is determined by whether the input file + is 7- or 8-bit. If the input file is 7-bit, the default coding is + [127,117] while the default coding for an 8-bit file is a [255, + 235]. This allows for 5 or 10 error characters in 127 or 255 + symbols to be corrected respectively. The number of errors that + can be corrected can be overridden by the variable T + + If the file is not an integer multiple of the message size (127 or + 255) in length, then the file is padded with the EOT (ASCII + character 4) character before decoding + + See also: rsencof + + +File: comms.info, Node: rsenc, Next: rsencof, Prev: rsdecof, Up: Function Reference + +9.1.111 rsenc +------------- + + -- Loadable Function: CODE = rsenc (MSG, N, K) + -- Loadable Function: CODE = rsenc (MSG, N, K, G) + -- Loadable Function: CODE = rsenc (MSG, N, K, FCR, PRIM) + -- Loadable Function: CODE = rsenc (..., PARPOS) + Encodes the message MSG using a [N,K] Reed-Solomon coding. The + variable MSG is a Galois array with K columns and an arbitrary + number of rows. Each row of MSG represents a single block to be + coded by the Reed-Solomon coder. The coded message is returned in + the Galois array CODE containing N columns and the same number of + rows as MSG. + + The use of 'rsenc' can be seen in the following short example. + + m = 3; n = 2^m -1; k = 3; + msg = gf ([1 2 3; 4 5 6], m); + code = rsenc (msg, n, k); + + If N does not equal '2^M-1', where m is an integer, then a shorten + Reed-Solomon coding is used where zeros are added to the start of + each row to obtain an allowable codeword length. The returned CODE + has these prepending zeros stripped. + + By default the generator polynomial used in the Reed-Solomon coding + is based on the properties of the Galois Field in which MSG is + given. This default generator polynomial can be overridden by a + polynomial in G. Suitable generator polynomials can be constructed + with 'rsgenpoly'. FCR is an integer value, and it is taken to be + the first consecutive root of the generator polynomial. The + variable PRIM is then the primitive element used to construct the + generator polynomial, such that + + G = (X - A^B) * (X - A^(B+PRIM)) * ... * (X - A^(B+2*T*PRIM-1)). + + where B is equal to 'FCR * PRIM'. By default FCR and PRIM are both + 1. + + By default the parity symbols are placed at the end of the coded + message. The variable PARPOS controls this positioning and can + take the values '"beginning\"' or '\"end\"'. See also: gf, rsdec, + rsgenpoly + + +File: comms.info, Node: rsencof, Next: rsgenpoly, Prev: rsenc, Up: Function Reference + +9.1.112 rsencof +--------------- + + -- Function File: rsencof (IN, OUT) + -- Function File: rsencof (IN, OUT, T) + -- Function File: rsencof (..., PAD) + + Encodes an ASCII file using a Reed-Solomon coder. The input file + is defined by IN and the result is written to the output file OUT + The type of coding to use is determined by whether the input file + is 7- or 8-bit. If the input file is 7-bit, the default coding is + [127,117] while the default coding for an 8-bit file is a [255, + 235]. This allows for 5 or 10 error characters in 127 or 255 + symbols to be corrected respectively. The number of errors that + can be corrected can be overridden by the variable T + + If the file is not an integer multiple of the message size (127 or + 255) in length, then the file is padded with the EOT (ASCII + character 4) characters before coding. Whether these characters + are written to the output is defined by the PAD variable. Valid + values for PAD are "pad" (the default) and "nopad", which write or + not the padding respectively + + See also: rsdecof + + +File: comms.info, Node: rsgenpoly, Next: scatterplot, Prev: rsencof, Up: Function Reference + +9.1.113 rsgenpoly +----------------- + + -- Function File: G = rsgenpoly (N, K) + -- Function File: G = rsgenpoly (N, K, P) + -- Function File: G = rsgenpoly (N, K, P, B, S) + -- Function File: G = rsgenpoly (N, K, P, B) + -- Function File: [G, T] = rsgenpoly (...) + + Creates a generator polynomial for a Reed-Solomon coding with + message length of K and codelength of N. N must be greater than K + and their difference must be even. The generator polynomial is + returned on G as a polynomial over the Galois Field GF(2^M) where N + is equal to '2^M-1'. If M is not integer the next highest integer + value is used and a generator for a shorten Reed-Solomon code is + returned + + The elements of G represent the coefficients of the polynomial in + descending order. If the length of G is lg, then the generator + polynomial is given by + + G(0) * x^(lg-1) + G(1) * x^(lg-2) + ... + G(lg-1) * x + G(lg) + + If P is defined then it is used as the primitive polynomial of the + Galois Field GF(2^M). The default primitive polynomial will be + used if P is equal to [] + + The variables B and S determine the form of the generator + polynomial in the following manner + + G = (X - A^(B*S)) * (X - A^((B+1)*S)) * ... * (X - A^((B+2*T-1)*S)) + + where T is '(N-K)/2', and A is the primitive element of the Galois + Field. Therefore B is the first consecutive root of the generator + polynomial and S is the primitive element to generate the + polynomial roots + + If requested the variable T, which gives the error correction + capability of the Reed-Solomon code See also: gf, rsenc, rsdec + + +File: comms.info, Node: scatterplot, Next: shannonfanodeco, Prev: rsgenpoly, Up: Function Reference + +9.1.114 scatterplot +------------------- + + -- Function File: scatterplot (X) + -- Function File: scatterplot (X, N) + -- Function File: scatterplot (X, N, OFF) + -- Function File: scatterplot (X, N, OFF, STR) + -- Function File: scatterplot (X, N, OFF, STR, H) + -- Function File: H = scatterplot (...) + + Display the scatter plot of a signal. The signal X can be either + in one of three forms + + A real vector + In this case the signal is assumed to be real and represented + by the vector X. The scatterplot is plotted along the x axis + only + A complex vector + In this case the in-phase and quadrature components of the + signal are plotted separately on the x and y axes respectively + A matrix with two columns + In this case the first column represents the in-phase and the + second the quadrature components of a complex signal and are + plotted on the x and y axes respectively + + Each point of the scatter plot is assumed to be separated by N + elements in the signal. The first element of the signal to plot is + determined by OFF. By default N is 1 and OFF is 0 + + The string STR is a plot style string (example "r+"), and by + default is the default gnuplot point style + + The figure handle to use can be defined by H. If H is not given, + then the next available figure handle is used. The figure handle + used in returned on HOUT See also: eyediagram + + +File: comms.info, Node: shannonfanodeco, Next: shannonfanodict, Prev: scatterplot, Up: Function Reference + +9.1.115 shannonfanodeco +----------------------- + + -- Function File: shannonfanodeco (HCODE, DICT) + + Returns the original signal that was Shannon-Fano encoded. The + signal was encoded using 'shannonfanoenco'. This function uses a + dict built from the 'shannonfanodict' and uses it to decode a + signal list into a Shannon-Fano list. Restrictions include hcode + is expected to be a binary code; returned signal set that strictly + belongs in the 'range [1,N]', with 'N = length (dict)'. Also dict + can only be from the 'shannonfanodict (...)' routine. Whenever + decoding fails, those signal values are indicated by -1, and we + successively try to restart decoding from the next bit that hasn't + failed in decoding, ad-infinitum + + An example use of 'shannonfanodeco' is + hd = shannonfanodict (1:4, [0.5 0.25 0.15 0.10]); + hcode = shannonfanoenco (1:4, hd) + => hcode = [0 1 0 1 1 0 1 1 1 0] + shannonfanodeco (hcode, hd) + => [1 2 3 4] + See also: shannonfanoenco, shannonfanodict + + +File: comms.info, Node: shannonfanodict, Next: shannonfanoenco, Prev: shannonfanodeco, Up: Function Reference + +9.1.116 shannonfanodict +----------------------- + + -- Function File: shannonfanodict (SYMBOLS, SYMBOL_PROBABILITES) + + Returns the code dictionary for source using Shannon-Fano algorithm + Dictionary is built from SYMBOL_PROBABILITIES using the + Shannon-Fano scheme. Output is a dictionary cell-array, which are + codewords, and correspond to the order of input probability + + cw = shannonfanodict (1:4, [0.5 0.25 0.15 0.1]); + assert (redundancy (cw, [0.5 0.25 0.15 0.1]), 0.25841, 0.001) + shannonfanodict (1:5, [0.35 0.17 0.17 0.16 0.15]) + shannonfanodict (1:8, [8 7 6 5 5 4 3 2] / 40) + See also: shannonfanoenc, shannonfanodec + + +File: comms.info, Node: shannonfanoenco, Next: sqrt, Prev: shannonfanodict, Up: Function Reference + +9.1.117 shannonfanoenco +----------------------- + + -- Function File: shannonfanoenco (HCODE, DICT) + + Returns the Shannon-Fano encoded signal using DICT This function + uses a DICT built from the 'shannonfanodict' and uses it to encode + a signal list into a Shannon-Fano code Restrictions include a + signal set that strictly belongs in the 'range [1,N]' with 'N = + length (dict)'. Also dict can only be from the 'shannonfanodict' + routine An example use of 'shannonfanoenco' is + + hd = shannonfanodict (1:4, [0.5 0.25 0.15 0.10]); + shannonfanoenco (1:4, hd) + => [0 1 0 1 1 0 1 1 1 0] + See also: shannonfanodeco, shannonfanodict + + +File: comms.info, Node: sqrt, Next: sum, Prev: shannonfanoenco, Up: Function Reference + +9.1.118 sqrt +------------ + + -- Loadable Function: sqrt (X) + Compute the square root of X, element by element, in a Galois Field + See also: exp + + +File: comms.info, Node: sum, Next: sumsq, Prev: sqrt, Up: Function Reference + +9.1.119 sum +----------- + + -- Loadable Function: sum (X, DIM) + Sum of elements along dimension DIM of Galois array. If DIM is + omitted, it defaults to 1 (column-wise sum) + + +File: comms.info, Node: sumsq, Next: symerr, Prev: sum, Up: Function Reference + +9.1.120 sumsq +------------- + + -- Loadable Function: sumsq (X, DIM) + Sum of squares of elements along dimension DIM of Galois array If + DIM is omitted, it defaults to 1 (column-wise sum of squares) + + This function is equivalent to computing + gsum (x .* conj (x), dim) + but it uses less memory + + +File: comms.info, Node: symerr, Next: syndtable, Prev: sumsq, Up: Function Reference + +9.1.121 symerr +-------------- + + -- Function File: [NUM, RATE] = symerr (A, B) + -- Function File: [NUM, RATE] = symerr (..., FLAG) + -- Function File: [NUM, RATE IND] = symerr (...) + + Compares two matrices and returns the number of symbol errors and + the symbol error rate. The variables A and B can be either: + + Both matrices + In this case both matrices must be the same size and then by + default the return values NUM and RATE are the overall number + of symbol errors and the overall symbol error rate + One column vector + In this case the column vector is used for symbol error + comparison column-wise with the matrix. The returned values + NUM and RATE are then row vectors containing the number of + symbol errors and the symbol error rate for each of the + column-wise comparisons. The number of rows in the matrix + must be the same as the length of the column vector + One row vector + In this case the row vector is used for symbol error + comparison row-wise with the matrix. The returned values NUM + and RATE are then column vectors containing the number of + symbol errors and the symbol error rate for each of the + row-wise comparisons. The number of columns in the matrix + must be the same as the length of the row vector + + This behavior can be overridden with the variable FLAG. FLAG can + take the value "column-wise", "row-wise" or "overall". A + column-wise comparison is not possible with a row vector and + visa-versa + + +File: comms.info, Node: syndtable, Next: systematize, Prev: symerr, Up: Function Reference + +9.1.122 syndtable +----------------- + + -- Loadable Function: T = syndtable (H) + Create the syndrome decoding table from the parity check matrix H. + Each row of the returned matrix T represents the error vector in a + received symbol for a certain syndrome. The row selected is + determined by a conversion of the syndrome to an integer + representation, and using this to reference each row of T. See + also: hammgen, cyclgen + + +File: comms.info, Node: systematize, Next: vec2mat, Prev: syndtable, Up: Function Reference + +9.1.123 systematize +------------------- + + -- Function File: systematize (G) + + Given G, extract P parity check matrix. Assume row-operations in + GF(2) G is of size KxN, when decomposed through row-operations into + a I of size KxK identity matrix, and a parity check matrix P of + size Kx(N-K) + + Most arbitrary code with a given generator matrix G, can be + converted into its systematic form using this function + + This function returns 2 values, first is default being GX the + systematic version of the G matrix, and then the parity check + matrix P + + g = [1 1 1 1; 1 1 0 1; 1 0 0 1]; + [gx, p] = systematize (g); + => gx = [1 0 0 1; 0 1 0 0; 0 0 1 0]; + => p = [1 0 0]; + See also: bchpoly, biterr + + +File: comms.info, Node: vec2mat, Next: wgn, Prev: systematize, Up: Function Reference + +9.1.124 vec2mat +--------------- + + -- Function File: M = vec2mat (V, C) + -- Function File: M = vec2mat (V, C, D) + -- Function File: [M, ADD] = vec2mat (...) + + Converts the vector V into a C column matrix with row priority + arrangement and with the final column padded with the value D to + the correct length. By default D is 0. The amount of padding + added to the matrix is returned in ADD + + +File: comms.info, Node: wgn, Prev: vec2mat, Up: Function Reference + +9.1.125 wgn +----------- + + -- Function File: Y = wgn (M, N, P) + -- Function File: Y = wgn (M, N, P, IMP) + -- Function File: Y = wgn (M, N, P, IMP, SEED) + -- Function File: Y = wgn (..., TYPE) + -- Function File: Y = wgn (..., OUTPUT) + + Returns a M-by-N matrix Y of white Gaussian noise. P specifies the + power of the output noise, which is assumed to be referenced to an + impedance of 1 Ohm, unless IMP explicitly defines the impedance + + If SEED is defined then the randn function is seeded with this + value + + The arguments TYPE and OUTPUT must follow the above numerical + arguments, but can be specified in any order. TYPE specifies the + units of P, and can be "dB", "dBW", "dBm" or "linear". "dB" is in + fact the same as "dBW" and is keep as a misnomer of Matlab. The + units of "linear" are in Watts + + The OUTPUT variable should be either "real" or "complex". If the + output is complex then the power P is divided equally between the + real and imaginary parts + + See also: randn, awgn + + + +Tag Table: +Node: Top71 +Node: Introduction388 +Node: Random Signals923 +Node: Signal Creation1596 +Node: Signal Analysis9791 +Node: Source Coding13805 +Node: Quantization14028 +Node: PCM Coding16275 +Node: Arithmetic Coding16626 +Node: Dynamic Range Compression16876 +Node: Block Coding18082 +Node: Data Formats18637 +Node: Binary Block Codes20830 +Node: BCH Codes26409 +Node: Reed-Solomon Codes29083 +Node: Representation of Reed-Solomon Messages29336 +Node: Creating and Decoding Messages31260 +Node: Shortened Reed-Solomon Codes35268 +Node: Convolutional Coding36430 +Node: Trellis Structure36901 +Node: Convolutional Encoding38704 +Node: Modulations39974 +Node: Special Filters40267 +Node: Galois Fields40416 +Node: Galois Field Basics40617 +Node: Creating Galois Fields42736 +Node: Primitive Polynomials44863 +Node: Accessing Internal Fields47406 +Node: Function Overloading49036 +Node: Known Problems50743 +Node: Manipulating Galois Fields52637 +Node: Expressions manipulation and assignment53000 +Node: Unary operations56392 +Node: Arithmetic operations57146 +Node: Comparison operations60342 +Node: Polynomial manipulations61539 +Node: Linear Algebra66614 +Node: Signal Processing68670 +Node: Function Reference71720 +Node: ademodce83482 +Node: amdemod85656 +Node: ammod86167 +Node: amodce86651 +Node: apkconst88580 +Node: awgn90318 +Node: bchdeco91553 +Node: bchenco93790 +Node: bchpoly95417 +Node: berconfint98643 +Node: bi2de99506 +Node: bin2gray100324 +Node: biterr101208 +Node: bsc103205 +Node: comms103448 +Node: compand104991 +Node: conv106260 +Node: convenc106667 +Node: convmtx107749 +Node: cosets108485 +Node: cyclgen108814 +Node: cyclpoly110051 +Node: de2bi111222 +Node: decode112465 +Node: deconv117181 +Node: deintrlv117648 +Node: demodmap117902 +Node: det120400 +Node: dftmtx120599 +Node: diag121274 +Node: dpcmdeco122024 +Node: dpcmenco122541 +Node: dpcmopt123746 +Node: egolaydec125325 +Node: egolayenc126549 +Node: egolaygen127184 +Node: encode127592 +Node: exp131082 +Node: eyediagram131301 +Node: fft132920 +Node: fibodeco133246 +Node: fiboenco134256 +Node: fibosplitstream135519 +Node: filter136398 +Node: finddelay137575 +Node: fmdemod138148 +Node: fmmod138629 +Node: gen2par139219 +Node: genqamdemod139782 +Node: genqammod140162 +Node: gf140855 +Node: gftable140993 +Node: gfweight141378 +Node: golombdeco142330 +Node: golombenco143420 +Node: hammgen145396 +Node: helscanintrlv146313 +Node: huffmandeco146578 +Node: huffmandict147617 +Node: huffmanenco149330 +Node: ifft150067 +Node: intrlv150412 +Node: inv150660 +Node: inverse151032 +Node: isequal151214 +Node: isgalois151466 +Node: isprimitive151706 +Node: istrellis152037 +Node: lloyds152495 +Node: log154512 +Node: lu154731 +Node: lz77deco155741 +Node: lz77enco156206 +Node: matdeintrlv156632 +Node: matintrlv156936 +Node: minpol157238 +Node: modmap157622 +Node: oct2dec160371 +Node: pamdemod160685 +Node: pammod161541 +Node: poly2trellis162320 +Node: primpoly164433 +Node: prod165705 +Node: pskdemod165987 +Node: pskmod166862 +Node: qamdemod167660 +Node: qammod167925 +Node: qaskdeco168186 +Node: qaskenco169501 +Node: qfunc171294 +Node: qfuncinv171496 +Node: quantiz171714 +Node: randdeintrlv172652 +Node: randerr172948 +Node: randint174067 +Node: randintrlv175001 +Node: randsrc175281 +Node: rank176258 +Node: rcosfir176504 +Node: reedmullerdec177064 +Node: reedmullerenc178403 +Node: reedmullergen179148 +Node: reshape180142 +Node: ricedeco181161 +Node: riceenco182023 +Node: rledeco183457 +Node: rleenco183962 +Node: roots184512 +Node: rsdec184945 +Node: rsdecof187140 +Node: rsenc188096 +Node: rsencof190145 +Node: rsgenpoly191345 +Node: scatterplot193105 +Node: shannonfanodeco194684 +Node: shannonfanodict195876 +Node: shannonfanoenco196675 +Node: sqrt197466 +Node: sum197712 +Node: sumsq197976 +Node: symerr198380 +Node: syndtable200075 +Node: systematize200621 +Node: vec2mat201497 +Node: wgn201998 + +End Tag Table + + +Local Variables: +coding: utf-8 +End: diff --git a/doc/comms.texi b/doc/comms.texi new file mode 100644 index 0000000..9142f31 --- /dev/null +++ b/doc/comms.texi @@ -0,0 +1,6462 @@ +\input texinfo + +@setfilename comms.info + +@settitle Communications Package for Octave + +@titlepage +@title Communications Package for Octave +@subtitle November 2013 +@author David Bateman +@author Paul Kienzle +@author Laurent Mazet +@author Mike Miller +@page +@vskip 0pt plus 1filll +Copyright @copyright{} 2003-2013 + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the entire +resulting derived work is distributed under the terms of a permission +notice identical to this one. + +Permission is granted to copy and distribute translations of this manual +into another language, under the same conditions as for modified versions. +@end titlepage + +@contents + +@ifnottex +@node Top, Introduction +@top +@end ifnottex + +@menu +* Introduction:: +* Random Signals:: +* Source Coding:: +* Block Coding:: +* Convolutional Coding:: +* Modulations:: +* Special Filters:: +* Galois Fields:: +* Function Reference:: +@end menu + +@node Introduction, Random Signals, Top, Top +@chapter Introduction + +This is the manual for the Communications Package for GNU Octave. All +functions provided by this package are described in this manual. In addition +many functions from Octave and other Octave packages are useful to or +required by this package, and so they may also be explained or shown in +examples in this manual. + +This documentation is a work in progress, you are invited to help improve it +and submit patches. + +@node Random Signals, Source Coding, Introduction, Top +@chapter Random Signals + +The purpose of the functions described here is to create and add random +noise to a signal, to create random data and to analyze the eventually +errors in a received signal. The functions to perform these tasks can +be considered as either related to the creation or analysis of signals +and are treated separately below. + +It should be noted that the examples below are based on the output of a +random number generator, and so the user can not expect to exactly recreate +the examples below. + +@menu +* Signal Creation:: +* Signal Analysis:: +@end menu + +@node Signal Creation, Signal Analysis, , Random Signals +@section Signal Creation + +The signal creation functions here fall into to two classes. Those that +treat discrete data and those that treat continuous data. The basic +function to create discrete data is @code{randint}, that creates a +random matrix of equi-probable integers in a desired range. For example + +@example +octave:1> a = randint (3, 3, [-1, 1]) +a = + + 0 1 0 + -1 -1 1 + 0 1 1 +@end example + +@noindent +creates a 3-by-3 matrix of random integers in the range -1 to 1. To allow +for repeated analysis with the same random data, the function @code{randint} +allows the seed-value of the random number generator to be set. For instance + +@example +octave:1> a = randint (3, 3, [-1, 1], 1) +a = + + 0 1 1 + 0 -1 0 + 1 -1 -1 +@end example + +@noindent +will always produce the same set of random data. The range of the integers +to produce can either be a two element vector or an integer. In the case +of a two element vector all elements within the defined range can be produced. +In the case of an integer range @var{M}, @code{randint} returns the equi-probable +integers in the range +@tex +$[0:2^m-1]$. +@end tex +@ifnottex +[0:2^@var{m}-1]. +@end ifnottex + +The function @code{randsrc} differs from @code{randint} in that it allows +a random set of symbols to be created with a given probability. The symbols +can be real, complex or even characters. However characters and scalars +can not be mixed. For example + +@example +octave:1> a = randsrc (2, 2, "ab"); +octave:2> b = randsrc (4, 4, [1, 1i, -1, -1i]); +@end example + +@noindent +are both legal, while + +@example +octave:1> a = randsrc (2, 2, [1, "a"]); +@end example + +@noindent +is not legal. The alphabet from which the symbols are chosen can be either +a row vector or two row matrix. In the case of a row vector, all of the +elements of the alphabet are chosen with an equal probability. In the case +of a two row matrix, the values in the second row define the probability +that each of the symbols are chosen. For example + +@example +octave:1> a = randsrc (5, 5, [1, 1i, -1, -1i; 0.6 0.2 0.1 0.1]) +a = + + 1 + 0i 0 + 1i 0 + 1i 0 + 1i 1 + 0i + 1 + 0i 1 + 0i 0 + 1i 0 + 1i 1 + 0i + -0 - 1i 1 + 0i -1 + 0i 1 + 0i 0 + 1i + 1 + 0i 1 + 0i 1 + 0i 1 + 0i 1 + 0i + -1 + 0i -1 + 0i 1 + 0i 1 + 0i 1 + 0i +@end example + +@noindent +defines that the symbol '1' has a 60% probability, the symbol '1i' has +a 20% probability and the remaining symbols have 10% probability each. +The sum of the probabilities must equal one. Like @code{randint}, +@code{randsrc} accepts a fourth argument as the seed of the random +number generator allowing the same random set of data to be reproduced. + +The function @code{randerr} allows a matrix of random bit errors to be +created, for binary encoded messages. By default, @code{randerr} creates +exactly one errors per row, flagged by a non-zero value in the returned +matrix. That is + +@example +octave:1> a = randerr (5, 10) +a = + + 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 1 + 0 0 0 0 0 0 0 0 0 1 +@end example + +The number of errors per row can be specified as the third argument to +@code{randerr}. This argument can be either a scalar, a row vector or +a two row matrix. In the case of a scalar value, exactly this number of +errors will be created per row in the returned matrix. In the case of +a row vector, each element of the row vector gives a possible number of +equi-probable bit errors. The second row of a two row matrix defines +the probability of each number of errors occurring. For example + +@example +octave:1> n = 15; k = 11; nsym = 100; +octave:2> msg = randint (nsym, k); ## Binary vector of message +octave:3> code = encode (msg, n, k, "bch"); +octave:4> berrs = randerr (nsym, n, [0, 1; 0.7, 0.3]); +octave:5> noisy = mod (code + berrs, 2) ## Add errors to coded message +@end example + +@noindent +creates a vector @var{msg}, encodes it with a [15,11] BCH code, and then +add either none or one error per symbol with the chances of an error being +30%. As previously, @code{randerr} accepts a fourth argument as the seed of +the random number generator allowing the same random set of data to be +reproduced. + +All of the above functions work on discrete random signals. The functions +@code{wgn} and @code{awgn} create and add white Gaussian noise to continuous +signals. The function @code{wgn} creates a matrix of white Gaussian noise +of a certain power. A typical call to @code{wgn} is then + +@example +octave:1> nse = wgn (10, 10, 0); +@end example + +@noindent +which creates a 10-by-10 matrix of noise with a root mean squared power +of 0dBW relative to an impedance of +@tex +$1\Omega$. +@end tex +@ifnottex +1 Ohm. +@end ifnottex + +This effectively means that an equivalent result to the above can be +obtained with + +@example +octave:1> nse = randn (10, 10); +@end example + +The reference impedance and units of power to the function @code{wgn} +can however be modified, for example + +@example +octave:1> nse_30dBm_50Ohm = wgn (10000, 1, 30, 50, "dBm"); +octave:2> nse_0dBW_50Ohm = wgn (10000, 1, 0, 50, "dBW"); +octave:3> nse_1W_50Ohm = wgn (10000, 1, 1, 50, "linear"); +octave:4> [std(nse_30dBm_50Ohm), std(nse_0dBW_50Ohm), std(nse_1W_50Ohm)] +ans = + + 7.0805 7.1061 7.0730 +@end example + +Each of these produces a 1W signal referenced to a +@tex +$50\Omega$ +@end tex +@ifnottex +50 Ohm +@end ifnottex +impedance. @sc{matlab} uses the misnomer "dB" for "dBW", so "dB" is an +accepted type for @code{wgn} and is treated as a synonym for "dBW". + +In all cases, the returned matrix @var{v}, will be related to the input +power @var{p} and the impedance @var{Z} as + +@tex +$$p = {\sum_i \sum_j v(i,j)^2 \over Z} Watts$$ +@end tex +@ifnottex +@var{p} = sum (@var{v}(:) .^ 2 ) / @var{imp} Watts +@end ifnottex + +By default @code{wgn} produces real vectors of white noise. However, it can +produce both real and complex vectors like + +@example +octave:1> rnse = wgn (10000, 1, 0, "dBm", "real"); +octave:2> cnse = wgn (10000, 1, 0, "dBm", "complex"); +octave:3> [std(rnse), std(real (cnse)), std(imag (cnse)), std(cnse)] +ans = + + 0.031615 0.022042 0.022241 0.031313 +@end example + +@noindent +which shows that with a complex return value that the total power is the +same as a real vector, but that it is equally shared between the real and +imaginary parts. As previously, @code{wgn} accepts a fourth numerical argument +as the seed of the random number generator allowing the same random set of +data to be reproduced. That is + +@example +octave:1> nse = wgn (10, 10, 0, 0); +@end example + +@noindent +will always produce the same set of data. + +The final function to deal with the creation of random signals is +@code{awgn}, that adds noise at a certain level relative to a desired +signal. This function adds noise at a certain level to a desired +signal. An example call to @code{awgn} is + +@example +octave:1> x = [0:0.1:2*pi]; +octave:2> y = sin (x); +octave:3> noisy = awgn (y, 10, "measured") +@end example + +@ifnotinfo +@noindent +which produces a sine-wave with noise added as seen in Figure 1. + +@center @image{awgn} + +@center Figure 1: Sine-wave with 10dB signal-to-noise ratio +@end ifnotinfo + +@noindent +which adds noise with a 10dB signal-to-noise ratio to the measured power +in the desired signal. By default @code{awgn} assumes that the desired +signal is at 0dBW, and the noise is added relative to this assumed +power. This behavior can be modified by the third argument to @code{awgn}. +If the third argument is a numerical value, it is assumed to define the +power in the input signal, otherwise if the third argument is the string +"measured", as above, the power in the signal is measured prior to the +addition of the noise. + +The final argument to @code{awgn} defines the definition of the power and +signal-to-noise ratio in a similar manner to @code{wgn}. This final +argument can be either "dB" or "linear". In the first case the numerical +value of the input power is assumed to be in dBW and the signal-to-noise +ratio in dB. In the second case, the power is assumed to be in Watts +and the signal-to-noise ratio is expressed as a ratio. + +The return value of @code{awgn} will be in the same form as the input +signal. In addition if the input signal is real, the additive noise will +be real. Otherwise the additive noise will also be complex and the noise +will be equally split between the real and imaginary parts. + +As previously the seed to the random number generator can be specified +as the last argument to @code{awgn} to allow repetition of the same +scenario. That is + +@example +octave:1> x = [0:0.1:2*pi]; +octave:2> y = sin (x); +octave:3> noisy = awgn (y, 10, "dB", 0, "measured") +@end example + +@noindent +which uses the seed-value of 0 for the random number generator. + +@node Signal Analysis, , Signal Creation, Random Signals +@section Signal Analysis + +It is important to be able to evaluate the performance of a +communications system in terms of its bit-error and symbol-error +rates. Two functions @code{biterr} and @code{symerr} exist within this +package to calculate these values, both taking as arguments the +expected and the actually received data. The data takes the form +of matrices or vectors, with each element representing a single +symbol. They are compared in the following manner + +@table @asis +@item Both matrices +In this case both matrices must be the same size and then by default the +return values are the overall number of errors and the overall error rate. +@item One column vector +In this case the column vector is used for comparison column-wise +with the matrix. The return values are row vectors containing the number +of errors and the error rate for each column-wise comparison. The number +of rows in the matrix must be the same as the length of the column vector. +@item One row vector +In this case the row vector is used for comparison row-wise +with the matrix. The return values are column vectors containing the number +of errors and the error rate for each row-wise comparison. The number +of columns in the matrix must be the same as the length of the row vector. +@end table + +For the bit-error comparison, the size of the symbol is assumed to be the +minimum number of bits needed to represent the largest element in the +two matrices supplied. However, the number of bits per symbol can (and +in the case of random data should) be specified. As an example of the +use of @code{biterr} and @code{symerr}, consider the example + +@example +octave:1> m = 8; +octave:2> msg = randint (10, 10, 2^m); +octave:3> noisy = mod (msg + diag (1:10), 2^m); +octave:4> [berr, brate] = biterr (msg, noisy, m) +berr = 32 +brate = 0.040000 +octave:5> [serr, srate] = symerr (msg, noisy) +serr = 10 +srate = 0.10000 +@end example + +@noindent +which creates a 10-by-10 matrix adds 10 symbols errors to the data and then +finds the bit and symbol error-rates. + +Two other means of displaying the integrity of a signal are the +eye-diagram and the scatterplot. Although the functions +@code{eyediagram} and @code{scatterplot} have different appearance, the +information presented is similar and so are their inputs. The difference +between @code{eyediagram} and @code{scatterplot} is that @code{eyediagram} +segments the data into time intervals and plots the in-phase and +quadrature components of the signal against this time interval. While +@code{scatterplot} uses a parametric plot of quadrature versus in-phase +components. + +Both functions can accept real or complex signals in the following +forms. + +@table @asis +@item A real vector +In this case the signal is assumed to be real and represented by the vector +@var{x}. +@item A complex vector +In this case the in-phase and quadrature components of the signal are +assumed to be the real and imaginary parts of the signal. +@item A matrix with two columns +In this case the first column represents the in-phase and the second the +quadrature components of a complex signal. +@end table + +An example of the use of the function @code{eyediagram} is + +@example +octave:1> n = 50; +octave:2> ovsp = 50; +octave:3> x = 1:n; +octave:4> xi = 1:1/ovsp:n-0.1; +octave:5> y = randsrc (1, n, [1 + 1i, 1 - 1i, -1 - 1i, -1 + 1i]); +octave:6> yi = interp1 (x, y, xi); +octave:7> noisy = awgn (yi, 15, "measured"); +octave:8> eyediagram (noisy, ovsp); +@end example + +@ifnotinfo +@noindent +which produces a eye-diagram of a noisy signal as seen in Figure 2. Similarly +an example of the use of the function @code{scatterplot} is + +@center @image{eyediagram} + +@center Figure 2: Eye-diagram of a QPSK like signal with 15dB signal-to-noise ratio +@end ifnotinfo +@ifinfo +Similarly an example of the use of the function @code{scatterplot} is +@end ifinfo + +@example +octave:1> n = 200; +octave:2> ovsp = 5; +octave:3> x = 1:n; +octave:4> xi = 1:1/ovsp:n-0.1; +octave:5> y = randsrc (1, n, [1 + 1i, 1 - 1i, -1 - 1i, -1 + 1i]); +octave:6> yi = interp1 (x, y, xi); +octave:7> noisy = awgn (yi, 15, "measured"); +octave:8> f = scatterplot (noisy, 1, 0, "b"); +octave:9> hold on; +octave:10> scatterplot (noisy, ovsp, 0, "r+", f); +@end example + +@ifnotinfo +@noindent +which produces a scatterplot of a noisy signal as seen in Figure 3. + +@center @image{scatterplot} + +@center Figure 3: Scatterplot of a QPSK like signal with 15dB signal-to-noise ratio +@end ifnotinfo + +@node Source Coding, Block Coding, Random Signals, Top +@chapter Source Coding + +@menu +* Quantization:: +* PCM Coding:: +* Arithmetic Coding:: +* Dynamic Range Compression:: +@end menu + +@node Quantization, PCM Coding, , Source Coding +@section Quantization + +An important aspect of converting an analog signal to the digital domain +is quantization. This is the process of mapping a continuous signal to a +set of defined values. Octave contains two functions to perform quantization, +@code{lloyds} creates an optimal mapping of the continuous signal to a fixed +number of levels and @code{quantiz} performs the actual quantization. + +The set of quantization points to use is represented by a partitioning +table (@var{table}) of the data and the signal levels (@var{codes} to +which they are mapped. The partitioning @var{table} is monotonically +increasing and if x falls within the range given by two points of this +table then it is mapped to the corresponding code as seen in Table 1. + +@center Table 1: Table quantization partitioning and coding + +@multitable @columnfractions 0.1 0.4 0.4 0.1 +@item @tab x < table(1) @tab codes(1) @tab +@item @tab table(1) <= x < table(2) @tab codes(2) @tab +@item @tab @dots{} @tab @dots{} @tab +@item @tab table(i-1) <= x < table(i) @tab codes(i) @tab +@item @tab @dots{} @tab @dots{} @tab +@item @tab table(n-1) <= x < table(n) @tab codes(n) @tab +@item @tab table(n-1) <= x @tab codes(n+1) @tab +@end multitable + +These partition and coding tables can either be created by the user of +using the function @code{lloyds}. For instance the use of a linear +mapping can be seen in the following example. + +@example +octave:1> m = 8; +octave:2> n = 1024; +octave:3> table = 2*[0:m-1]/m - 1 + 1/m; +octave:4> codes = 2*[0:m]/m - 1; +octave:5> x = 4*pi*[0:(n-1)]/(n-1); +octave:6> y = cos (x); +octave:7> [i, z] = quantiz (y, table, codes); +@end example + +If a training signal is known that well represents the expected signals, +the quantization levels can be optimized using the @code{lloyds} function. +For example the above example can be continued + +@example +octave:8> [table2, codes2] = lloyds (y, table, codes); +octave:9> [i, z2] = quantiz (y, table2, codes2); +@end example + +@noindent +to use the mapping suggested by the function @code{lloyds}. It should be +noted that the mapping given by @code{lloyds} is highly dependent on the +training signal used. So if this signal does not represent a realistic +signal to be quantized, then the partitioning suggested by @code{lloyds} +will be sub-optimal. + +@node PCM Coding, Arithmetic Coding, Quantization, Source Coding +@section PCM Coding + +The DPCM function @code{dpcmenco}, @code{dpcmdeco} and @code{dpcmopt} +implement a form of predictive quantization, where the predictability +of the signal is used to further compress it. These functions are +not yet implemented. + +@node Arithmetic Coding, Dynamic Range Compression, PCM Coding, Source Coding +@section Arithmetic Coding + +The arithmetic coding functions @code{arithenco} and @code{arithdeco} are +not yet implemented. + +@node Dynamic Range Compression, , Arithmetic Coding, Source Coding +@section Dynamic Range Compression + +The final source coding function is @code{compand} which is used to +compress and expand the dynamic range of a signal. For instance +consider a logarithm quantized by a linear partitioning. Such a +partitioning is very poor for this large dynamic range. @code{compand} +can then be used to compress the signal prior to quantization, with +the signal being expanded afterwards. For example + +@example +octave:1> mu = 1.95; +octave:2> x = [0.01:0.01:2]; +octave:3> y = log (x); +octave:4> V = max (abs (y)); +octave:5> [i, z, d] = quantiz (y, [-4.875:0.25:0.875], [-5:0.25:1]); +octave:6> c = compand (y, minmu, V, "mu/compressor"); +octave:7> [i2, c2] = quantiz (c, [-4.875:0.25:0.875], [-5:0.25:1]); +octave:8> z2 = compand (c2, minmu, max (abs (c2)), "mu/expander"); +octave:9> d2 = sumsq (y - z2) / length (y); +octave:10> [d, d2] +ans = + + 0.0053885 0.0029935 +@end example + +@noindent +which demonstrates that the use of @code{compand} can significantly +reduce the distortion due to the quantization of signals with a large +dynamic range. + +@node Block Coding, Convolutional Coding, Source Coding, Top +@chapter Block Coding + +The error-correcting codes available in this package are discussed here. +These codes work with blocks of data, with no relation between one block +and the next. These codes create codewords based on the messages to +transmit that contain redundant information that allow the recovery of +the original message in the presence of errors. + +@menu +* Data Formats:: +* Binary Block Codes:: +* BCH Codes:: +* Reed-Solomon Codes:: +@end menu + +@node Data Formats, Binary Block Codes, , Block Coding +@section Data Formats + +All of the codes described in this section are binary and share similar +data formats. The exception is the Reed-Solomon coder which has a +significantly longer codeword length in general and therefore uses a +different representation to efficiently pass data. The user should refer +to the section about the Reed-Solomon codes for the data format used for +Reed-Solomon codes. + +In general @var{k} bits of data are considered to represent a single +message symbol. These @var{k} bits are coded into @var{n} bits of +data representing the codeword. The data can therefore be grouped +in one of three manners, to emphasis this grouping into bits, messages +and codewords + +@table @asis +@item A binary vector +Each element of the vector is either one or zero. If the data represents +an uncoded message the vector length should be an integer number of @var{k} +in length. +@item A binary matrix +In this case the data is ones and zeros grouped into rows, with each +representing a single message or codeword. The number of columns in the +matrix should be equal to @var{k} in the case of a uncoded message or +@var{n} in the case of a coded message. +@item A non-binary vector +In this case each element of the vector represents a message or codeword +in an integer format. The bits of the message or codeword are represented +by the bits of the vector elements with the least-significant bit +representing the first element in the message or codeword. +@end table + +An example demonstrating the relationship between the three data +formats can be seen below. + +@example +octave:1> k = 4; +octave:2> bin_vec = randint (k*10, 1); # Binary vector format +octave:3> bin_mat = reshape (bin_vec, k, 10)'; # Binary matrix format +octave:4> dec_vec = bi2de (bin_mat); # Decimal vector format +@end example + +The functions within this package will return data in the same format +to which it is given. It should be noted that internally the binary +matrix format is used, and thus if the message or codeword length is +large it is preferable to use the binary format to avoid internal +rounding errors. + +@node Binary Block Codes, BCH Codes, Data Formats, Block Coding +@section Binary Block Codes + +All of the codes presented here can be characterized by their + +@table @asis +@item Generator Matrix +A @var{k}-by-@var{n} matrix @var{G} to generate the codewords @var{C} from +the messages @var{T} by the matrix multiplication +@tex +$ {\bf C} = {\bf T} {\bf G}$. +@end tex +@ifnottex +@var{C} = @var{T} * @var{G}. +@end ifnottex +@item Parity Check Matrix +A '@var{n}-@var{k}'-by-@var{n} matrix @var{H} to check the parity of the +received symbols. If +@tex +$ {\bf H} {\bf R} = {\bf S} \ne 0$, +@end tex +@ifnottex +@var{H} * @var{R} = @var{S} != 0, +@end ifnottex +then an error has been detected. @var{S} can be used with the syndrome +table to correct this error +@item Syndrome Table +A 2^@var{k}-by-@var{n} matrix @var{ST} with the relationship of the error +vectors to the non-zero parities of the received symbols. That is, if +the received symbol is represented as +@tex +$ {\bf R} = ( {\bf T} + {\bf E} )\ mod\ 2$, +@end tex +@ifnottex +@var{R} = mod (@var{T} + @var{E}, 2), +@end ifnottex +then the error vector @var{E} is +@tex +${\bf ST}({\bf S})$. +@end tex +@ifnottex +@var{ST}(@var{S}). +@end ifnottex +@end table + +It is assumed for most of the functions in this package that the generator +matrix will be in a 'standard' form. That is the generator matrix can be +represented by + +@tex +$$ +{\bf G} = +\left[\matrix{g_{11} & g_{12} & \ldots & g_{1k} & 1 & 0 & \ldots & 0 \cr + g_{21} & g_{22} & & g_{2k} & 0 & 1 & & 0 \cr + \vdots & & & \vdots & \vdots& & & \vdots \cr + g_{k1} & g_{k2} & \ldots & g_{kk} & 0 & 0 & \ldots & 1}\right] +$$ +@end tex +@ifnottex +@example +@group + g(1,1) g(1,2) ... g(1,k) 1 0 ... 0 + g(2,1) g(2,2) g(2,k) 0 1 ... 0 + . . . . + . . . . + . . . . + g(k,1) g(k,2) ... g(k,k) 0 0 ... 1 +@end group +@end example +@end ifnottex + +@noindent +or + +@tex +$$ +{\bf G} = +\left[\matrix{1 & 0 & \ldots & 0 & g_{11} & g_{12} & \ldots & g_{1k} \cr + 0 & 1 & & 0 & g_{21} & g_{22} & & g_{2k} \cr + \vdots & & & \vdots & \vdots & & & \vdots \cr + 0 & 0 & \ldots & 1 & g_{k1} & g_{k2} & \ldots & g_{kk}}\right] +$$ +@end tex +@ifnottex +@example +@group + 1 0 ... 0 g(1,1) g(1,2) ... g(1,k) + 0 1 ... 0 g(2,1) g(2,2) g(2,k) + . . . . + . . . . + . . . . + 0 0 ... 1 g(k,1) g(k,2) ... g(k,k) +@end group +@end example +@end ifnottex + +@noindent +and similarly the parity check matrix can be represented by a combination +of an identity matrix and a square matrix. + +Some of the codes can also have their representation in terms of a +generator polynomial that can be used to create the generator and parity +check matrices. In the case of BCH codes, this generator polynomial is +used directly in the encoding and decoding without ever explicitly forming +the generator or parity check matrix. + +The user can create their own generator and parity check matrices, or +they can rely on the functions @code{hammgen}, @code{cyclgen} and +@code{cyclpoly}. The function @code{hammgen} creates parity check and +generator matrices for Hamming codes, while @code{cyclpoly} and +@code{cyclgen} create generator polynomials and matrices for generic +cyclic codes. An example of their use is + +@example +octave:1> m = 3; +octave:2> n = 2^m - 1; +octave:2> k = 4; +octave:3> [par, gen] = hammgen (m); +octave:4> [par2, gen2] = cyclgen (n, cyclpoly (n, k)); +@end example + +@noindent +which create identical parity check and generator matrices for the +[7,4] Hamming code. + +The syndrome table of the codes can be created with the function +@code{syndtable}, in the following manner + +@example +octave:1> [par, gen] = hammgen (3); +octave:2> st = syndtable (par); +@end example + +There exists two auxiliary functions @code{gen2par} and @code{gfweight}, +that convert between generator and parity check matrices and calculate +the Hamming distance of the codes. For instance + +@example +octave:1> par = hammgen (3); +octave:2> gen = gen2par (par); +octave:3> gfweight (gen) +ans = 3 +@end example + +It should be noted that for large values of @var{n}, the generator, +parity check and syndrome table matrices are very large. There is +therefore an internal limitation on the size of the block codes that +can be created that limits the codeword length @var{n} to less than 64. +This is still excessively large for the syndrome table, so use caution +with these codes. These limitations do not apply to the Reed-Solomon +or BCH codes. + +The top-level encode and decode functions are @code{encode} and +@code{decode}, which can be used with all codes, except the Reed-Solomon +code. The basic call to both of these functions passes the message +to code/decode, the codeword length, the message length and the type +of coding to use. There are four basic types that are available with +these functions + +@table @asis +@item "linear" +Generic linear block codes +@item "cyclic" +Cyclic linear block codes +@item "hamming" +Hamming codes +@item "bch" +Bose Chaudhuri Hocquenghem (BCH) block codes +@end table + +It is not possible to distinguish between a binary vector and a decimal +vector coding of the messages that just happens to only have ones and +zeros. Therefore the functions @code{encode} and @code{decode} must be +told the format of the messages in the following manner. + +@example +octave:1> m = 3; +octave:2> n = 7; +octave:3> k = 4; +octave:4> msg_bin = randint (10, k); +octave:5> cbin = encode (msg_bin, n, k, "hamming/binary"); +octave:5> cdec = encode (bi2de (msg), n, k, "hamming/decimal"); +@end example + +@noindent +which codes a binary matrix and a non-binary vector representation of a +message, returning the coded message in the same format. The functions +@code{encode} and @code{decode} by default accept binary coded +messages. Therefore "hamming" is equivalent to "hamming/binary". + +Except for the BCH codes, the function @code{encode} and @code{decode} +internally create the generator, parity check and syndrome table +matrices. Therefore if repeated calls to @code{encode} and @code{decode} +are made, it will often be faster to create these matrices externally +and pass them as an argument. For example + +@example +n = 15; +k = 11; +[par, gen] = hammgen (4); +code1 = code2 = zeros (100, 15) +for i = 1:100 + msg = get_msg (i); + code1(i,:) = encode (msg, n, k, "linear", gen); # This is faster + code2(i,:) = encode (msg, n, k, "hamming"); # than this !!! +endfor +@end example + +In the case of the BCH codes the low-level functions described in the +next section are used directly by the @code{encode} and @code{decode} +functions. + + +@node BCH Codes, Reed-Solomon Codes, Binary Block Codes, Block Coding +@section BCH Codes + +The BCH coder used here is based on code written by Robert Morelos-Zaragoza +(r.morelos-zaragoza@@ieee.org). This code was originally written in C +and has been converted for use as an Octave oct-file. + +@iftex +Called without arguments, @code{bchpoly} returns a table of valid BCH +error correcting codes and their error-correction capability +as seen in Table 1. + +@center Table 2: Table of valid BCH codes with codeword length less than 511. + +@multitable @columnfractions .083 .083 .083 .083 .083 .083 .083 .083 .083 .083 .083 .083 +@item N @tab K @tab T @tab N @tab K @tab T @tab N @tab K @tab T @tab N @tab K @tab T +@item 7 @tab 4 @tab 1 @tab 127 @tab 36 @tab 15 @tab 255 @tab 45 @tab 43 @tab 511 @tab 268 @tab 29 +@item 15 @tab 11 @tab 1 @tab 127 @tab 29 @tab 21 @tab 255 @tab 37 @tab 45 @tab 511 @tab 259 @tab 30 +@item 15 @tab 7 @tab 2 @tab 127 @tab 22 @tab 23 @tab 255 @tab 29 @tab 47 @tab 511 @tab 250 @tab 31 +@item 15 @tab 5 @tab 3 @tab 127 @tab 15 @tab 27 @tab 255 @tab 21 @tab 55 @tab 511 @tab 241 @tab 36 +@item 31 @tab 26 @tab 1 @tab 127 @tab 8 @tab 31 @tab 255 @tab 13 @tab 59 @tab 511 @tab 238 @tab 37 +@item 31 @tab 21 @tab 2 @tab 255 @tab 247 @tab 1 @tab 255 @tab 9 @tab 63 @tab 511 @tab 229 @tab 38 +@item 31 @tab 16 @tab 3 @tab 255 @tab 239 @tab 2 @tab 511 @tab 502 @tab 1 @tab 511 @tab 220 @tab 39 +@item 31 @tab 11 @tab 5 @tab 255 @tab 231 @tab 3 @tab 511 @tab 493 @tab 2 @tab 511 @tab 211 @tab 41 +@item 31 @tab 6 @tab 7 @tab 255 @tab 223 @tab 4 @tab 511 @tab 484 @tab 3 @tab 511 @tab 202 @tab 42 +@item 63 @tab 57 @tab 1 @tab 255 @tab 215 @tab 5 @tab 511 @tab 475 @tab 4 @tab 511 @tab 193 @tab 43 +@item 63 @tab 51 @tab 2 @tab 255 @tab 207 @tab 6 @tab 511 @tab 466 @tab 5 @tab 511 @tab 184 @tab 45 +@item 63 @tab 45 @tab 3 @tab 255 @tab 199 @tab 7 @tab 511 @tab 457 @tab 6 @tab 511 @tab 175 @tab 46 +@item 63 @tab 39 @tab 4 @tab 255 @tab 191 @tab 8 @tab 511 @tab 448 @tab 7 @tab 511 @tab 166 @tab 47 +@item 63 @tab 36 @tab 5 @tab 255 @tab 187 @tab 9 @tab 511 @tab 439 @tab 8 @tab 511 @tab 157 @tab 51 +@item 63 @tab 30 @tab 6 @tab 255 @tab 179 @tab 10 @tab 511 @tab 430 @tab 9 @tab 511 @tab 148 @tab 53 +@item 63 @tab 24 @tab 7 @tab 255 @tab 171 @tab 11 @tab 511 @tab 421 @tab 10 @tab 511 @tab 139 @tab 54 +@item 63 @tab 18 @tab 10 @tab 255 @tab 163 @tab 12 @tab 511 @tab 412 @tab 11 @tab 511 @tab 130 @tab 55 +@item 63 @tab 16 @tab 11 @tab 255 @tab 155 @tab 13 @tab 511 @tab 403 @tab 12 @tab 511 @tab 121 @tab 58 +@item 63 @tab 10 @tab 13 @tab 255 @tab 147 @tab 14 @tab 511 @tab 394 @tab 13 @tab 511 @tab 112 @tab 59 +@item 63 @tab 7 @tab 15 @tab 255 @tab 139 @tab 15 @tab 511 @tab 385 @tab 14 @tab 511 @tab 103 @tab 61 +@item 127 @tab 120 @tab 1 @tab 255 @tab 131 @tab 18 @tab 511 @tab 376 @tab 15 @tab 511 @tab 94 @tab 62 +@item 127 @tab 113 @tab 2 @tab 255 @tab 123 @tab 19 @tab 511 @tab 367 @tab 17 @tab 511 @tab 85 @tab 63 +@item 127 @tab 106 @tab 3 @tab 255 @tab 115 @tab 21 @tab 511 @tab 358 @tab 18 @tab 511 @tab 76 @tab 85 +@item 127 @tab 99 @tab 4 @tab 255 @tab 107 @tab 22 @tab 511 @tab 349 @tab 19 @tab 511 @tab 67 @tab 87 +@item 127 @tab 92 @tab 5 @tab 255 @tab 99 @tab 23 @tab 511 @tab 340 @tab 20 @tab 511 @tab 58 @tab 91 +@item 127 @tab 85 @tab 6 @tab 255 @tab 91 @tab 25 @tab 511 @tab 331 @tab 21 @tab 511 @tab 49 @tab 93 +@item 127 @tab 78 @tab 7 @tab 255 @tab 87 @tab 26 @tab 511 @tab 322 @tab 22 @tab 511 @tab 40 @tab 95 +@item 127 @tab 71 @tab 9 @tab 255 @tab 79 @tab 27 @tab 511 @tab 313 @tab 23 @tab 511 @tab 31 @tab 109 +@item 127 @tab 64 @tab 10 @tab 255 @tab 71 @tab 29 @tab 511 @tab 304 @tab 25 @tab 511 @tab 28 @tab 111 +@item 127 @tab 57 @tab 11 @tab 255 @tab 63 @tab 30 @tab 511 @tab 295 @tab 26 @tab 511 @tab 19 @tab 119 +@item 127 @tab 50 @tab 13 @tab 255 @tab 55 @tab 31 @tab 511 @tab 286 @tab 27 @tab 511 @tab 10 @tab 127 +@item 127 @tab 43 @tab 14 @tab 255 @tab 47 @tab 42 @tab 511 @tab 277 @tab 28 @tab @tab @tab +@end multitable + +@end iftex +@ifnottex +Called without arguments, @code{bchpoly} returns a table of valid BCH +error correcting codes and their error-correction capability. +@end ifnottex +The first returned column of @code{bchpoly} is the codeword length, +the second the message length and the third the error correction capability +of the code. Called with one argument, @code{bchpoly} returns similar +output, but only for the specified codeword length. In this manner codes +with codeword length greater than 511 can be found. + +In general the codeword length is of the form @code{2^@var{m} - 1}, where +@var{m} is an integer. However if [@var{n},@var{k}] is a valid BCH +code, then it is also possible to use a shortened BCH form of the form +@code{[@var{n}-@var{x},@var{k}-@var{x}]}. + +With two or more arguments, @code{bchpoly} is used to find the generator +polynomial of a valid BCH code. For instance + +@example +octave:1> bchpoly (15, 7) +ans = + + 1 0 0 0 1 0 1 1 1 + +octave:2> bchpoly (14, 6) +ans = + + 1 0 0 0 1 0 1 1 1 +@end example + +@noindent +show that the generator polynomial of a [15,7] BCH code with the default +primitive polynomial is + +@tex +$$ 1 + x^4 + x^6 + x^7 + x^8 $$ +@end tex +@ifnottex +1 + @var{x} ^ 4 + @var{x} ^ 6 + @var{x} ^ 7 + @var{x} ^ 8 +@end ifnottex + +Using a different primitive polynomial to define the Galois Field over +which the BCH code is defined results in a different generator polynomial +as can be seen in the example. + +@example +octave:1> bchpoly ([1 1 0 0 1], 7) +ans = + + 1 0 0 0 1 0 1 1 1 + +octave:2> bchpoly ([1 0 0 1 1], 7) +ans = + + 1 1 1 0 1 0 0 0 1 +@end example + +It is recommend not to convert the generator polynomials created by +@code{bchpoly} into generator and parity check matrices with the +BCH codes, as the underlying BCH software is faster than the generic +coding software and can treat significantly longer codes. + +As well as using the @code{encode} and @code{decode} functions previously +discussed, the user can directly use the low-level BCH functions +@code{bchenco} and @code{bchdeco}. In this case the messages must be +in the format of a binary matrix with @var{k} columns + +@example +octave:1> n = 31; +octave:2> pgs = bchpoly (n); +octave:3> pg = pgs(floor (rand () * (rows (pgs) + 1)),:); # Pick a poly +octave:4> k = pg(2); +octave:5> t = pg(3); +octave:6> msg = randint (10, k); +octave:7> code = bchenco (msg, n, k); +octave:8> noisy = code + [ones(10, 1), zeros(10, n-1)]; +octave:9> dec = bchdeco (code, k, t); +@end example + +@node Reed-Solomon Codes, , BCH Codes, Block Coding +@section Reed-Solomon Codes + +@menu +* Representation of Reed-Solomon Messages:: +* Creating and Decoding Messages:: +* Shortened Reed-Solomon Codes:: +@end menu + +@node Representation of Reed-Solomon Messages, Creating and Decoding Messages, , Reed-Solomon Codes +@subsection Representation of Reed-Solomon Messages + +The Reed-Solomon coder used in this package is based on code written by +Phil Karn (http://www.ka9q.net/code/fec). This code was originally written +in C and has been converted for use as an Octave oct-file. + +Reed-Solomon codes are based on Galois Fields of even characteristics +GF(2^M). Many of the properties of Galois Fields are therefore important +when considering Reed-Solomon coders. + +The representation of the symbols of the Reed-Solomon code differs from +the other block codes, in that the other block codes use a binary +representation, while the Reed-Solomon code represents each m-bit symbol +by an integer. The elements of the message and codeword must be elements +of the Galois Field corresponding to the Reed-Solomon code. Thus to +code a message with a [7,5] Reed-Solomon code an example is + +@example +octave:1> m = 3; +octave:2> n = 7; +octave:3> k = 5; +octave:4> msg = gf (floor (2^m * rand (2, k)), m) +msg = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 5 0 6 3 2 + 4 1 3 1 2 + +octave:5> code = rsenc (msg, n, k) +code = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 5 0 6 3 2 3 5 + 4 1 3 1 2 6 3 +@end example + +The variable @var{n} is the codeword length of the Reed-Solomon coder, +while @var{k} is the message length. It should be noted that @var{k} +should be less than @var{n} and that @code{@var{n} - @var{k}} should be +even. The error correcting capability of the Reed-Solomon code is then +@code{(@var{n} - @var{k})/2} symbols. @var{m} is the number of bits per +symbol, and is related to @var{n} by @code{@var{n} = 2^@var{m} - 1}. +For a valid Reed-Solomon coder, @var{m} should be between 3 and 16. + +@node Creating and Decoding Messages, Shortened Reed-Solomon Codes, Representation of Reed-Solomon Messages, Reed-Solomon Codes +@subsection Creating and Decoding Messages + +The Reed-Solomon encoding function requires at least three arguments. The +first @var{msg} is the message in encodes, the second is @var{n} the codeword +length and @var{k} is the message length. Therefore @var{msg} must have +@var{k} columns and the output will have @var{n} columns of symbols. + +The message itself is many up of elements of a Galois Field +GF(2^M). Normally, The order of the Galois Field (M), is related to the +codeword length by @code{@var{n} = 2^@var{m} - 1}. Another important +parameter when determining the behavior of the Reed-Solomon coder is +the primitive polynomial of the Galois Field (see @code{gf}). Thus +the messages + +@example +octave:1> msg0 = gf ([0, 1, 2, 3], 3); +octave:2> msg1 = gf ([0, 1, 2, 3], 3, 13); +@end example + +@noindent +will not result in the same Reed-Solomon coding. Finally, the parity of +the Reed-Solomon code are generated with the use of a generator +polynomial. The parity symbols are then generated by treating the message +to encode as a polynomial and finding the remainder of the division of +this polynomial by the generator polynomial. Therefore the generator +polynomial must have as many roots as @code{@var{n} - @var{k}}. Whether +the parity symbols are placed before or afterwards the message will then +determine which end of the message is the most-significant term of the +polynomial representing the message. The parity symbols are therefore +different in these two cases. The position of the parity symbols can be +chosen by specifying "beginning" or "end" to @code{rsenc} and @code{rsdec}. +By default the parity symbols are placed after the message. + +Valid generator polynomials can be constructed with the @code{rsgenpoly} +function. The roots of the generator polynomial are then defined by + +@tex +$$ +g = (x - A^{bs}) (x - A^{(b+1)s}) \cdots (x - A ^{(b+2t-1)s}). +$$ +@end tex +@ifnottex + +@example +@var{g} = (@var{x} - A^(@var{b}*@var{s})) * (@var{x} - A^((@var{b}+1)*@var{s})) * @dots{} * (@var{x} - A^((@var{b}+2*@var{t}-1)*@var{s})). +@end example +@end ifnottex + +@noindent +where @var{t} is @code{(@var{n} - @var{k})/2}, A is the primitive element +of the Galois Field, @var{b} is the first consecutive root, and @var{s} +is the step between roots. Generator polynomial of this form are constructed +by @code{rsgenpoly} and can be passed to both @code{rsenc} and @code{rsdec}. +It is also possible to pass the @var{b} and @var{s} values directly to +@code{rsenc} and @code{rsdec}. In the case of @code{rsdec} passing @var{b} +and @var{s} can make the decoding faster. + +Consider the example below. + +@example +octave:1> m = 8; +octave:2> n = 2^m - 1; +octave:3> k = 223; +octave:4> prim = 391; +octave:5> b = 112; +octave:6> s = 11; +octave:7> gg = rsgenpoly (n, k, prim, b, s); +octave:8> msg = gf (floor (2^m * rand (17, k)), m, prim); +octave:9> code = rsenc (msg, n, k, gg); +octave:10> noisy = code + [toeplitz([ones(1,17)], zeros(1,17)), zeros(17,238)]; +octave:11> [dec, nerr] = rsdec (msg, n, k, b, s); +octave:12> nerr' +ans = + + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 -1 + +octave:13> any (msg' != dec') +ans = + + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 +@end example + +This is an interesting example in that it demonstrates many of the +additional arguments of the Reed-Solomon functions. In particular +this example approximates the CCSDS standard Reed-Solomon coder, +lacking only the dual-basis lookup tables used in this standard. +The CCSDS uses non-default values to all of the basic functions +involved in the Reed-Solomon encoding, since it has a non-default +primitive polynomial, generator polynomial, etc. + +The example creates 17 message blocks and adds between 1 and 17 error +symbols to these block. As can be seen @var{nerr} gives the number of +errors corrected. In the case of 17 introduced errors @var{nerr} +equals -1, indicating a decoding failure. This is normal as the +correction ability of this code is up to 16 error symbols. Comparing +the input message and the decoding it can be seen that as expected, +only the case of 17 errors has not been correctly decoded. + +@node Shortened Reed-Solomon Codes, , Creating and Decoding Messages, Reed-Solomon Codes +@subsection Shortened Reed-Solomon Codes + +In general the codeword length of the Reed-Solomon coder is chosen so +that it is related directly to the order of the Galois Field by the +formula @code{@var{n} = 2^@var{m} - 1}. Although, the underlying +Reed-Solomon coding must operate over valid codeword length, there +are sometimes reasons to assume that the codeword length will be shorter. +In this case the message is padded with zeros before coding, and the +zeros are stripped from the returned block. For example consider the +shortened [6,4] Reed-Solomon below + +@example +octave:1> m = 3; +octave:2> n = 6; +octave:3> k = 4; +octave:4> msg = gf (floor (2^m * rand (2, k)), m) +msg = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 7 0 2 5 + 1 5 7 1 + +octave:5> code = rsenc (msg, n, k) +code = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 7 0 2 5 2 3 + 1 5 7 1 0 2 +@end example + + +@node Convolutional Coding, Modulations, Block Coding, Top +@chapter Convolutional Coding + +Some initial support for convolutional codes is provided by the +functions described in this chapter. Convolutional codes are different +from block codes in that the sequence of preceding symbols is taken +into account when computing the output symbol of the coder. + +@menu +* Trellis Structure:: +* Convolutional Encoding:: +@end menu + +@node Trellis Structure, Convolutional Encoding, , Convolutional Coding +@section Trellis Structure + +Like block codes, convolutional codes can be described by a set of +generator polynomials. Each polynomial describes the combination of +current and previous input symbols used to compute one output bit of +the encoder. + +The state transitions and outputs of a convolutional encoder can also be +described by a trellis diagram. This diagram describes the transitions +between states and the outputs of the encoder as a function of the +current state and the current input symbol. A trellis structure can be +created from a set of generator polynomials, specified as octal numbers +by convention, + +@example +octave:1> g0 = 13; +octave:2> g1 = 17; +octave:3> trellis = poly2trellis (4, [g0, g1]); +@end example + +@noindent +where @var{g0} and @var{g1} are the two polynomials of a rate 1/2 +encoder with a constraint length of 4. The returned trellis structure +contains the following fields + +@table @samp +@item numInputSymbols +The number of possible input symbols in the input sequence. +@item numOutputSymbols +The number of possible output symbols in the encoded sequence. +@item numStates +The number of possible states that the encoder can take. +@item nextStates +The state transition table for the encoder. Each row contains the +(zero-based) indices of the states reachable from the state represented +by that row for each possible input symbol. +@item outputs +The output table for the encoder. Each row contains the (octal-encoded) +output symbols produced by the encoder in the state represented by that +row for each possible input symbol. +@end table + +To check if a variable references a structure that is a valid trellis +describing a convolutional encoder, use the @code{istrellis} function. + +@node Convolutional Encoding, , Trellis Structure, Convolutional Coding +@section Convolutional Encoding + +The convolutional encoding function takes the message to be encoded and +a trellis describing the encoder. The message must be a binary vector +containing an even number of symbols. For example, using the encoder +from the previous section, + +@example +octave:1> trellis = poly2trellis (4, [13, 17]); +octave:2> msg = [1 1 0 1 1 0 0 0]; +octave:3> out = convenc (msg, trellis) +out = + + 1 1 1 0 1 0 1 1 0 1 1 0 0 0 1 1 +@end example + +The initial state of the encoder can also be passed in to @code{convenc}, +and the ending state can be read with an optional output argument. +Encoding a different vector with a different initial state using the +same encoder, + +@example +octave:4> msg = [0 1 1 0 1 0 1 1]; +octave:5> [out, state] = convenc (msg, trellis, [], 4) +out = + + 0 1 0 0 0 1 1 0 1 1 1 0 0 0 0 1 + +state = 6 +@end example + +@noindent +returns both the encoded array and the final state of the convolutional +encoder. This can be used to encode data in blocks, for example, saving +and restoring the internal state of the encoder for each subsequent +input block. + +@node Modulations, Special Filters, Convolutional Coding, Top +@chapter Modulations + +To be written. + +Currently have functions amodce, ademodce, apkconst, demodmap, modmap, +qaskdeco, qaskenco, genqammod, pamdemod, pammod, pskdemod and pskmod. + +@node Special Filters, Galois Fields, Modulations, Top +@chapter Special Filters + +To be written. + +@node Galois Fields, Function Reference, Special Filters, Top +@chapter Galois Fields + +@menu +* Galois Field Basics:: +* Manipulating Galois Fields:: +@end menu + +@node Galois Field Basics, Manipulating Galois Fields, , Galois Fields +@section Galois Field Basics + +A Galois Field is a finite algebraic field. This package implements a +Galois Field type in Octave having 2^M members where M is an integer +between 1 and 16. Such fields are denoted as GF(2^M) and are used in +error correcting codes in communications systems. Galois Fields having +odd numbers of elements are not implemented. + +The @emph{primitive element} of a Galois Field has the property that all +elements of the Galois Field can be represented as a power of this element. +The @emph{primitive polynomial} is the minimum polynomial of some primitive +element in GF(2^M) and is irreducible and of order M. This means that the +primitive element is a root of the primitive polynomial. + +The elements of the Galois Field GF(2^M) are represented as the values +0 to 2^M -1 by Octave. The first two elements represent the zero and unity +values of the Galois Field and are unique in all fields. The element +represented by 2 is the primitive element of the field and all elements can +be represented as combinations of the primitive element and unity as follows + +@multitable @columnfractions .33 .33 .33 +@item Integer @tab Binary @tab Element of GF(2^M) +@item 0 @tab 000 @tab @code{0} +@item 1 @tab 001 @tab @code{1} +@item 2 @tab 010 @tab @code{A} +@item 3 @tab 011 @tab @code{A + 1} +@item 4 @tab 100 @tab @code{A^2} +@item 5 @tab 101 @tab @code{A^2 + 1} +@item 6 @tab 110 @tab @code{A^2 + A} +@item 7 @tab 111 @tab @code{A^2 + A + 1} +@end multitable + +It should be noted that there is often more than a single primitive +polynomial of GF(2^M). Each Galois Field over a different primitive +polynomial represents a different realization of the Field. The +representations above however rest valid. + +@menu +* Creating Galois Fields:: +* Primitive Polynomials:: +* Accessing Internal Fields:: +* Function Overloading:: +* Known Problems:: +@end menu + +@node Creating Galois Fields, Primitive Polynomials, , Galois Field Basics +@subsection Creating Galois Fields + +To work with a Galois Field GF(2^M) in Octave, you must first create a variable +that Octave recognizes as a Galois Field. This is done with the function +@code{gf (@var{a}, @var{m})} as follows. + +@example +octave:1> a = [0:7]; +octave:2> b = gf (a, 4) +b = +GF(2^4) array. Primitive Polynomial = D^4+D+1 (decimal 19) + +Array elements = + + 0 1 2 3 4 5 6 7 +@end example + +This creates an array @var{b} with 8 elements that Octave recognizes as a +Galois Field. The field is created with the default primitive polynomial for +the field GF(2^4). It can be verified that a variable is in fact a Galois +Field with the functions @code{isgalois} or @code{whos}. + +@example +octave:3> isgalois (a) +ans = 0 +octave:4> isgalois (b) +ans = 1 +octave:5> whos +Variables in the current scope: + + Attr Name Size Bytes Class + ==== ==== ==== ===== ===== + a 1x8 24 double + b 1x8 32 galois + +Total is 16 elements using 56 bytes +@end example + +It is also possible to create a Galois Field with an arbitrary primitive +polynomial. However, if the polynomial is not a primitive polynomial of +the field, and error message is returned. For instance. + +@example +octave:1> a = [0:7]; +octave:2> b = gf (a, 4, 25) +b = +GF(2^4) array. Primitive Polynomial = D^4+D^3+1 (decimal 25) + +Array elements = + + 0 1 2 3 4 5 6 7 + +octave:3> c = gf (a, 4, 21) +error: gf: primitive polynomial (21) of Galois Field must be irreducible +@end example + +The function @code{gftable} is included for compatibility with @sc{matlab}. In +@sc{matlab} this function is used to create the lookup tables used to accelerate +the computations over the Galois Field and store them to a file. However +Octave stores these parameters for all of the fields currently in use and +so this function is not required, although it is silently accepted. + +@node Primitive Polynomials, Accessing Internal Fields, Creating Galois Fields, Galois Field Basics +@subsection Primitive Polynomials + +The function @code{gf (@var{a}, @var{m})} creates a Galois Field using the default primitive +polynomial. However there exists many possible primitive polynomials for most +Galois Fields. Two functions exist for identifying primitive polynomials, +@code{isprimitive} and @code{primpoly}. @code{primpoly (@var{m}, @var{opt})} is +used to identify the primitive polynomials of the fields GF(2^M). For example + +@example +octave:1> primpoly (4) + +Primitive polynomial(s) = + +D^4+D+1 + +ans = 19 +@end example + +@noindent +identifies the default primitive polynomials of the field GF(2^M), which +is the same as @code{primpoly (4, "min")}. All of the primitive polynomials +of a field can be identified with the function @code{primpoly (@var{m}, "all")}. +For example + +@example +octave:1> primpoly (4, "all") + +Primitive polynomial(s) = + +D^4+D+1 +D^4+D^3+1 + +ans = + + 19 25 +@end example + +@noindent +while @code{primpoly (@var{m}, "max")} returns the maximum primitive polynomial +of the field, which for the case above is 25. The function @code{primpoly} +can also be used to identify the primitive polynomials having only a +certain number of non-zero terms. For instance + +@example +octave:1> primpoly (5, 3) + +Primitive polynomial(s) = + +D^5+D^2+1 +D^5+D^3+1 + +ans = + + 37 41 +@end example + +@noindent +identifies the polynomials with only three terms that can be used as +primitive polynomials of GF(2^5). If no primitive polynomials existing +having the requested number of terms then @code{primpoly} returns an +empty vector. That is + +@example +octave:1> primpoly (5, 2) +warning: primpoly: No primitive polynomial satisfies the given constraints + +ans = [](1x0) +@end example + +As can be seen above, @code{primpoly} displays the polynomial forms the +the polynomials that it finds. This output can be suppressed with the +"nodisplay" option, while the returned value is left unchanged. + +@example +octave:1> primpoly (4, "all", "nodisplay") +ans = + + 19 25 +@end example + +@code{isprimitive (@var{a})} identifies whether the elements of @var{a} can +be used as primitive polynomials of the Galois Fields GF(2^M). Consider +as an example the fields GF(2^4). The primitive polynomials of these fields +must have an order m and so their integer representation must be between +16 and 31. Therefore @code{isprimitive} can be used in a similar manner to +@code{primpoly} as follows + +@example +octave:1> find (isprimitive (16:31)) + 15 +ans = + + 19 25 +@end example + +@noindent +which finds all of the primitive polynomials of GF(2^4). + +@node Accessing Internal Fields, Function Overloading, Primitive Polynomials, Galois Field Basics +@subsection Accessing Internal Fields + +Once a variable has been defined as a Galois Field, the parameters of the +field of this structure can be obtained by adding a suffix to the variable. +Valid suffixes are '.m', '.prim_poly' and '.x', which return the order of the +Galois Field, its primitive polynomial and the data the variable contains +respectively. For instance + +@example +octave:1> a = [0:7]; +octave:2> b = gf (a, 4); +octave:3> b.m +ans = 4 +octave:4> b.prim_poly +ans = 19 +octave:5> c = b.x; +octave:6> whos +Variables in the current scope: + + Attr Name Size Bytes Class + ==== ==== ==== ===== ===== + a 1x8 24 double + b 1x8 32 galois + c 1x8 64 double + +Total is 24 elements using 120 bytes +@end example + +@c Note that if code compiled with GALOIS_DISP_PRIVATES then '.n', '.alpha_to' +@c and '.index_of' are also available. These give 2^m-1, the lookup table +@c and its inverse respectively. + +Please note that it is explicitly forbidden to modify the Galois field by +accessing these variables. For instance + +@example +octave:1> a = gf ([0:7], 3); +octave:2> a.prim_poly = 13; +@end example + +@noindent +is explicitly forbidden. The result of this will be to replace the +Galois array @var{a} with a structure @var{a} with a single element +called '.prim_poly'. To modify the order or primitive polynomial of a +field, a new field must be created and the data copied. That is + +@example +octave:1> a = gf ([0:7], 3); +octave:2> a = gf (a.x, a.m, 13); +@end example + +@node Function Overloading, Known Problems, Accessing Internal Fields, Galois Field Basics +@subsection Function Overloading + +An important consideration in the use of the Galois Field package is +that many of the internal functions of Octave, such as @code{roots}, can +not accept Galois Fields as an input. This package therefore uses Octave +classes to @emph{overload} the internal Octave functions with equivalent +functions that work with Galois Fields, so that the standard function names +can be used. + +The version of the function that is chosen is determined by the first +argument of the function. This is a temporary situation until the +Galois Field class constructor can be rewritten to allow the use of the +@code{superiorto} function to define the galois class with a higher +precedence. So, considering the @code{filter} function, +if the first argument is a @emph{Matrix}, then the normal version of +the function is called regardless of whether the other arguments of the +function are Galois vectors or not. + +Other Octave functions work correctly with Galois Fields and so overloaded +versions are not necessary. This include such functions as @code{size} and +@code{polyval}. + +It is also useful to use the '.x' option discussed in the previous section, +to extract the raw data of the Galois field for use with some functions. An +example is + +@example +octave:1> a = minpol (gf (14, 5)); +octave:2> b = de2bi (a.x, [], "left-msb"); +@end example + +@noindent +converts the polynomial form of the minimum polynomial of 14 in GF(2^5) into +an integer. Finally help for the Galois specific versions of the functions +must explicitly call the correct function as + +@example +octave:1> help @@galois/conv +@end example + +@node Known Problems, , Function Overloading, Galois Field Basics +@subsection Known Problems + +Please review the following list of known problems with the Galois type +before reporting a bug against this package. + +@table @asis +@item Saving and loading Galois variables + +Saving a Galois variable to a file is as simple as + +@example +octave:1> a = gf (@dots{}); +octave:2> save a.mat a +@end example + +@noindent +where @var{a} is any Galois variable. Galois variables can be saved in the +Octave binary and ASCII formats, as well as the HDF5 format. To load a +Galois variable from a file, the Galois type must already be registered to +the Octave interpreter prior to the call to @code{load}. If no Galois +variables have been created yet, you will have to do something like + +@example +octave:1> dummy = gf (1); +octave:2> load a.mat +@end example + +@item Logarithm of zero does not return NaN +The logarithm of zero in a Galois field is not defined. However, to avoid +segmentation faults in later calculations the logarithm of zero is defined +as @code{2^@var{m} - 1}, whose value is not the logarithm of any other value +in the Galois field. A warning is also shown to tell the user about the +problem. For example + +@example +octave:1> m = 3; +octave:2> a = log (gf ([0:2^m-1], m)) +warning: log of zero undefined in Galois field +a = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 7 0 1 3 2 6 4 5 +@end example + +To fix this problem would require a major rewrite of all code, adding +an exception for the case of NaN to all basic operators. These +exceptions will certainly slow the code down. + +@item Speed +The code was written piecemeal with no attention to optimization. Some +operations may be slower than they could be. Contributions are welcome. + +@end table + +@node Manipulating Galois Fields, , Galois Field Basics, Galois Fields +@section Manipulating Galois Fields + +@menu +* Expressions manipulation and assignment:: +* Unary operations:: +* Arithmetic operations:: +* Comparison operations:: +* Polynomial manipulations:: +* Linear Algebra:: +* Signal Processing:: +@end menu + +@node Expressions manipulation and assignment, Unary operations, , Manipulating Galois Fields +@subsection Expressions, manipulation and assignment + +Galois variables can be treated in similar manner to other variables within +Octave. For instance Galois fields can be accessed using index expressions +in a similar manner to all other Octave matrices. For example + +@example +octave:1> a = gf ([[0:7]; [7:-1:0]], 3) +a = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 0 1 2 3 4 5 6 7 + 7 6 5 4 3 2 1 0 + +octave:2> b = a(1,:) +b = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 0 1 2 3 4 5 6 7 +@end example + +Galois arrays can equally use indexed assignments. That is, the data +in the array can be partially replaced, on the condition that the two +fields are identical. An example is + +@example +octave:1> a = gf (ones (2, 8), 3); +octave:2> b = gf (zeros (1, 8), 3); +octave:3> a(1,:) = b +a = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 0 0 0 0 0 0 0 0 + 1 1 1 1 1 1 1 1 +@end example + +Implicit conversions between normal matrices and Galois arrays are possible. +For instance data can be directly copied from a Galois array to a real matrix +as follows. + +@example +octave:1> a = gf (ones (2, 8), 3); +octave:2> b = zeros (2, 8); +octave:3> b(2,:) = a(2,:) +b = + + 0 0 0 0 0 0 0 0 + 1 1 1 1 1 1 1 1 +@end example + +The inverse is equally possible, with the proviso that the data in the matrix +is valid in the Galois field. For instance + +@example +octave:1> a = gf ([0:7], 3); +octave:2> a(1) = 1; +@end example + +@noindent +is valid, while + +@example +octave:1> a = gf ([0:7], 3); +octave:2> a(1) = 8; +@end example + +@noindent +is not, since 8 is not an element of GF(2^3). This is a basic rule of +manipulating Galois arrays. That is matrices and scalars can be used in +conjunction with a Galois array as long as they contain valid data +within the Galois field. In this case they will be assumed to be of the +same field. + +Galois arrays can also be concatenated with real matrices or with other +Galois arrays in the same field. For example + +@example +octave:1> a = [gf([0:7], 3); gf([7:-1:0], 3)]; +octave:2> b = [a, a]; +octave:3> c = [a, eye(2)]; +octave:3> whos +Variables in the current scope: + + Attr Name Size Bytes Class + ==== ==== ==== ===== ===== + a 2x8 64 galois + b 2x16 128 galois + c 2x10 80 galois + +Total is 68 elements using 272 bytes +@end example + +Other basic manipulations of Galois arrays are + +@table @code +@item isempty +Returns true if the Galois array is empty. + +@item size +Returns the number of rows and columns in the Galois array. + +@item length +Returns the length of a Galois vector, or the maximum of rows or columns +of Galois arrays. + +@item find +Find the indexes of the non-zero elements of a Galois array. + +@item diag +Create a diagonal Galois array from a Galois vector, or extract a diagonal +from a Galois array. + +@item reshape +Change the shape of the Galois array. + +@end table + +@node Unary operations, Arithmetic operations, Expressions manipulation and assignment, Manipulating Galois Fields +@subsection Unary operations + +The same unary operators that are available for normal Octave matrices are +also available for Galois arrays. These operations are + +@table @code +@item +@var{x} +Unary plus. This operator has no effect on the operand. + +@item -@var{x} +Unary minus. Note that in a Galois Field this operator also has no effect +on the operand. + +@item !@var{x} +Returns true for zero elements of Galois Array. + +@item @var{x}' +Complex conjugate transpose. As the Galois Field only contains integer +values, this is equivalent to the transpose operator. + +@item @var{x}.' +Transpose of the Galois array. +@end table + +@node Arithmetic operations, Comparison operations, Unary operations, Manipulating Galois Fields +@subsection Arithmetic operations + +The available arithmetic operations on Galois arrays are the same as on +other Octave matrices. It should be noted that both operands must be in +the same Galois Field. If one operand is a Galois array and the second is +a matrix or scalar, then the second operand is silently converted to the +same Galois Field. The element(s) of these matrix or scalar must however +be valid members of the Galois field. Thus + +@example +octave:1> a = gf ([0:7], 3); +octave:2> b = a + [0:7]; +@end example + +@noindent +is valid, while + +@example +octave:1> a = gf ([0:7], 3); +octave:2> b = a + [1:8]; +@end example + +@noindent +is not, since 8 is not a valid element of GF(2^3). The available arithmetic +operators are + +@table @code +@item @var{x} + @var{y} +Addition. If both operands are Galois arrays or matrices, the number of rows +and columns must both agree. If one operand is a is a Galois array with a +single element or a scalar, its value is added to all the elements of the +other operand. The @code{+} operator on a Galois Field is equivalent to an +exclusive-or on normal integers. + +@item @var{x} .+ @var{y} +Element by element addition. This operator is equivalent to @code{+}. + +@item @var{x} - @var{y} +As both @code{+} and @code{-} in a Galois Field are equivalent to an +exclusive-or for normal integers, @code{-} is equivalent to the @code{+} +operator + +@item @var{x} .- @var{y} +Element by element subtraction. This operator is equivalent to @code{-}. + +@item @var{x} * @var{y} +Matrix multiplication. The number of columns of @var{x} must agree +with the number of rows of @var{y}. + +@item @var{x} .* @var{y} +Element by element multiplication. If both operands are matrices, the +number of rows and columns must both agree. + +@item @var{x} / @var{y} +Right division. This is conceptually equivalent to the expression + +@example +(inverse (y') * x')' +@end example + +@noindent +but it is computed without forming the inverse of @var{y'}. + +If the matrix is singular then an error occurs. If the matrix is +under-determined, then a particular solution is found (but not minimum +norm). If the solution is over-determined, then an attempt is made +to find a solution, but this is not guaranteed to work. + +@item @var{x} ./ @var{y} +Element by element right division. + +@item @var{x} \ @var{y} +Left division. This is conceptually equivalent to the expression + +@example +inverse (x) * y +@end example + +@noindent +but it is computed without forming the inverse of @var{x}. + +If the matrix is singular then an error occurs. If the matrix is +under-determined, then a particular solution is found (but not minimum +norm). If the solution is over-determined, then an attempt is made +to find a solution, but this is not guaranteed to work. + +@item @var{x} .\ @var{y} +Element by element left division. Each element of @var{y} is divided +by each corresponding element of @var{x}. + +@item @var{x} ^ @var{y} +@itemx @var{x} ** @var{y} +Power operator. If @var{x} and @var{y} are both scalars, this operator +returns @var{x} raised to the power @var{y}. Otherwise @var{x} must +be a square matrix raised to an integer power. + +@item @var{x} .^ @var{y} +@item @var{x} .** @var{y} +Element by element power operator. If both operands are matrices, the +number of rows and columns must both agree. + +@end table + +@node Comparison operations, Polynomial manipulations, Arithmetic operations, Manipulating Galois Fields +@subsection Comparison operations + +Galois variables can be tested for equality in the usual manner. That is + +@example +octave:1> a = gf ([0:7], 3); +octave:2> a == ones (1, 8) +ans = + + 0 1 0 0 0 0 0 0 + +octave:3> a != zeros (1, 8) +ans = + + 0 1 1 1 1 1 1 1 +@end example + +Likewise, Galois vectors can be tested against scalar values (whether they are +Galois or not). For instance + +@example +octave:4> a == 1 +ans = + + 0 1 0 0 0 0 0 0 +@end example + +To test if any or all of the values in a Galois array are non-zero, the +functions @code{any} and @code{all} can be used as normally. + +In addition the comparison operators @code{>}, @code{>=}, @code{<} and +@code{<=} are available. As elements of the Galois Field are modulus +2^@var{m}, all elements of the field are both greater than and less than +all others at the same time. Thus these comparison operators don't make +that much sense and are only included for completeness. The comparison is +done relative to the integer value of the Galois Field elements. + +@node Polynomial manipulations, Linear Algebra, Comparison operations, Manipulating Galois Fields +@subsection Polynomial manipulations + +A polynomial in GF(2^M) can be expressed as a vector in GF(2^M). For instance +if @var{a} is the @emph{primitive element}, then the example + +@example +octave:1> poly = gf ([2, 4, 5, 1], 3); +@end example + +@noindent +represents the polynomial + +@tex +$$ +poly = a x^3 + a^2 x^2 + (a^2 + 1) x + 1 +$$ +@end tex +@ifnottex +@example +poly = @var{a} * x^3 + @var{a}^2 * x^2 + (@var{a}^2 + 1) * x + 1 +@end example +@end ifnottex + +Arithmetic can then be performed on these vectors. For instance to add +to polynomials an example is + +@example +octave:1> poly1 = gf ([2, 4, 5, 1], 3); +octave:2> poly2 = gf ([1, 2], 3); +octave:3> sumpoly = poly1 + [0, 0, poly2] +sumpoly = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 2 4 4 3 +@end example + +Note that @var{poly2} must be zero padded to the same length as poly1 to +allow the addition to take place. + +Multiplication and division of Galois polynomials is equivalent to convolution +and de-convolution of vectors of Galois elements. Thus to multiply two +polynomials in GF(2^3). + +@example +octave:4> mulpoly = conv (poly1, poly2) +mulpoly = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 2 0 6 0 2 +@end example + +Likewise the division of two polynomials uses the de-convolution function +as follows + +@example +octave:5> [poly, remd] = deconv (mulpoly, poly2) +poly = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 2 4 5 1 + +remd = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 0 0 0 0 0 +@end example + +Note that the remainder of this division is zero, as we performed the inverse +operation to the multiplication. + +To evaluate a polynomial for a certain value in GF(2^M), use the Octave +function @code{polyval}. + +@example +octave:1> poly1 = gf ([2, 4, 5, 1], 3); ## a*x^3+a^2*x^2+(a^2+1)*x+1 +octave:2> x0 = gf ([0, 1, 2], 3); +octave:3> y0 = polyval (poly1, x0); +y0 = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 1 2 0 + +octave:4> a = gf (2, 3); ## The primitive element +octave:5> y1 = a .* x0.^3 + a.^2 .* x0.^2 + (a.^2 + 1) .* x0 + 1 +y1 = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 1 2 0 +@end example + +It is equally possible to find the roots of Galois polynomials with the +@code{roots} function. Using the polynomial above over GF(2^3), we can +find its roots in the following manner + +@example +octave:1> poly1 = gf ([2, 4, 5, 1], 3); +octave:2> root1 = roots (poly1) +root1 = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 2 + 5 + 5 +@end example + +Thus the example polynomial has 3 roots in GF(2^3) with one root of +multiplicity 2. We can check this answer with the @code{polyval} function +as follows + +@example +octave:3> check1 = polyval (poly1, root1) +check1 = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 0 + 0 + 0 +@end example + +@noindent +which as expected gives a zero vector. It should be noted that both the +number of roots and their value, will depend on the chosen field. Thus +for instance + +@example +octave:1> poly3 = gf ([2, 4, 5, 1], 3, 13); +octave:2> root3 = roots (poly3) +root3 = +GF(2^3) array. Primitive Polynomial = D^3+D^2+1 (decimal 13) + +Array elements = + + 5 +@end example + +@noindent +shows that in the field GF(2^3) with a different primitive polynomial, +has only one root exists. + +The minimum polynomial of an element of GF(2^M) is the minimum degree +polynomial in GF(2), excluding the trivial zero polynomial, that has +that element as a root. The fact that the minimum polynomial is in GF(2) +means that its coefficients are one or zero only. The @code{minpol} +function can be used to find the minimum polynomial as follows + +@example +octave:1> a = gf (2, 3); ## The primitive element +octave:2> b = minpol (a) +b = +GF(2) array. + +Array elements = + + 1 0 1 1 +@end example + +Note that the minimum polynomial of the primitive element is the primitive +polynomial. Elements of GF(2^M) sharing the same minimum polynomial form a +partitioning of the field. This partitioning can be found with the +@code{cosets} function as follows + +@example +octave:1> c = cosets (3) +c = +@{ + [1,1] = + GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + + Array elements = + + 1 + + [1,2] = + GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + + Array elements = + + 2 4 6 + + [1,3] = + GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + + Array elements = + + 3 5 7 + +@} +@end example + +@noindent +which returns a cell array containing all of the elements of the GF(2^3), +partitioned into groups sharing the same minimum polynomial. The function +@code{cosets} can equally accept a second argument defining the primitive +polynomial to use in its calculations (i.e. @code{cosets (@var{a}, @var{p})}). + +@node Linear Algebra, Signal Processing, Polynomial manipulations, Manipulating Galois Fields +@subsection Linear Algebra + +The basic linear algebra operation of this package is the LU factorization +of a Galois array. That is the Galois array @var{a} is factorized in the +following way + +@example +octave:2> [l, u, p] = lu (a) +@end example + +@noindent +such that @code{@var{p} * @var{a} = @var{l} * @var{u}}. The matrix @var{p} +contains row permutations of @var{a}, such that @var{l} and @var{u} are +strictly upper and low triangular. The Galois array @var{a} can be +rectangular. + +All other linear algebra operations within this package are based on this +LU factorization of a Galois array. An important consequence of this is that +no solution can be found for singular matrices, only a particular solution +will be found for under-determined systems of equation and the solution found +for over-determined systems is not always correct. This is identical to the +way @sc{matlab} performs linear algebra on Galois arrays. + +For instance consider the under-determined linear equation + +@example +octave:1> A = gf ([2, 0, 3, 3; 3, 1, 3, 1; 3, 1, 1, 0], 2); +octave:2> b = [0:2]'; +octave:3> x = A \ b; +@end example + +@noindent +gives the solution @code{@var{x} = [2, 0, 3, 2]}. There are in fact 4 +possible solutions to this linear system; @code{@var{x} = [3, 2, 2, 0]}, +@code{@var{x} = [0, 3, 1, 1]}, @code{@var{x} = [2, 0, 3, 2]} and +@code{@var{x} = [1, 1, 0, 3]}. No particular selection criteria are +applied to the chosen solution. + +In addition, because singular matrices cannot be solved, unless you +know the matrix is not singular, you should test the determinant of the +matrix prior to solving the linear system. For instance + +@example +octave:1> A = gf (floor (2^m * rand (3)), 2); +octave:2> b = [0:2]'; +octave:3> if (det (A) != 0); x = A \ b; y = b' / A; endif; +octave:4> r = rank (A); +@end example + +@noindent +solves the linear systems @code{@var{A} * @var{x} = @var{b}} and +@code{@var{y} * @var{A} = @var{b}}. Note that you do not need to take +into account rounding errors in the determinant, as the determinant can +only take values within the Galois Field. So if the determinant equals +zero, the array is singular. + +@node Signal Processing, , Linear Algebra, Manipulating Galois Fields +@subsection Signal Processing with Galois Fields + +Signal processing functions such as filtering, convolution, de-convolution +and Fourier transforms can be performed over Galois Fields. For instance +the @code{filter} function can be used with Galois vectors in the same +manner as usual. For instance + +@example +octave:1> b = gf ([2, 0, 0, 1, 0, 2, 0, 1], 2); +octave:2> a = gf ([2, 0, 1, 1], 2); +octave:3> x = gf ([1, zeros(1, 20)], 2); +octave:4> y = filter (b, a, x) +y = +GF(2^2) array. Primitive Polynomial = D^2+D+1 (decimal 7) + +Array elements = + + 1 0 3 0 2 3 1 0 1 3 3 1 0 1 3 3 1 0 1 3 3 +@end example + +@noindent +gives the impulse response of the filter defined by @var{a} and @var{b}. + +Two equivalent ways are given to perform the convolution of two Galois +vectors. Firstly the function @code{conv} can be used, or alternatively +the function @code{convmtx} can be used. The first of these function is +identical to the convolution function over real vectors, and has been +described in the section about multiplying two Galois polynomials. + +In the case where many Galois vectors will be convolved with the same +vector, the second function @code{convmtx} offers an alternative method +to calculate the convolution. If @var{a} is a column vector and @var{x} +is a column vector of length @var{n}, then + +@example +octave:1> m = 3; +octave:2> a = gf (floor (2^m * rand (4, 1)), m); +octave:3> b = gf (floor (2^m * rand (4, 1)), m); +octave:4> c0 = conv (a, b)'; +octave:5> c1 = convmtx (a, length (b)) * b; +octave:6> check = all (c0 == c1) +check = 1 +@end example + +@noindent +shows the equivalence of the two functions. The de-convolution function has +been previously described above. + +The final signal processing function available in this package are the +functions to perform Fourier transforms over a Galois field. Three +functions are available, @code{fft}, @code{ifft} and @code{dftmtx}. The +first two functions use the third to perform their work. Given an element +@var{a} of the Galois field GF(2^M), @code{dftmtx} returns the @code{2^M - 1} +square matrix used in the Fourier transforms with respect to @var{a}. The +minimum polynomial of @var{a} must be primitive in GF(2^M). In the case of +the @code{fft} function @code{dftmtx} is called with the primitive element of +the Galois Field as an argument. As an example + +@example +octave:1> m = 4; +octave:2> n = 2^m - 1; +octave:2> alph = gf (2, m); +octave:3> x = gf (floor (2^m * rand (n, 1)), m); +octave:4> y0 = fft (x); +octave:5> y1 = dftmtx (alph) * x; +octave:6> z0 = ifft (y0); +octave:7> z1 = dftmtx (1/alph) * y1; +octave:8> check = all (y0 == y1) & all (z0 == x) & all (z1 == x) +check = 1 +@end example + +In all cases, the length of the vector to be transformed must be +@code{2^M -1}. As the @code{dftmtx} creates a matrix representing the +Fourier transform, to limit the computational task only Fourier +transforms in GF(2^M), where M is less than or equal to 8, are supported. + +@node Function Reference, , Galois Fields, Top +@chapter Function Reference + +@iftex +@section Functions by Category +@subsection Random Signals +@table @asis +@item awgn +Add white Gaussian noise to a voltage signal +@item biterr +Compares two matrices and returns the number of bit errors and the bit error rate. +@item eyediagram +Plot the eye-diagram of a signal. +@item randerr +Generate a matrix of random bit errors. +@item randint +Generate a matrix of random binary numbers. +@item randsrc +Generate a matrix of random symbols. +@item scatterplot +Display the scatter plot of a signal. +@item symerr +Compares two matrices and returns the number of symbol errors and the symbol error rate. +@item wgn +Returns a M-by-N matrix Y of white Gaussian noise. +@item bsc +Send DATA into a binary symmetric channel with probability P of error one each symbol +@end table +@subsection Source Coding +@table @asis +@item compand +Compresses and expanding the dynamic range of a signal using a mu-law or or A-law algorithm +@item dpcmdeco +Decode using differential pulse code modulation (DPCM) +@item dpcmenco +Encode using differential pulse code modulation (DPCM) +@item dpcmopt +Optimize the DPCM parameters and codebook +@item huffmandeco +Decode signal encoded by 'huffmanenco' +@item huffmandict +Builds a Huffman code, given a probability list. +@item huffmanenco +Returns the Huffman encoded signal using DICT. +@item lloyds +Optimize the quantization table and codes to reduce distortion. +@item lz77deco +Lempel-Ziv 77 source algorithm decoding implementation. +@item lz77enco +Lempel-Ziv 77 source algorithm implementation. +@item quantiz +Quantization of an arbitrary signal relative to a partitioning +@item shannonfanodict +Returns the code dictionary for source using Shannon-Fano algorithm Dictionary is built from SYMBOL_PROBABILITIES using the Shannon-Fano scheme. +@item shannonfanoenco +Returns the Shannon-Fano encoded signal using DICT This function uses a DICT built from the 'shannonfanodict' and uses it to encode a signal list into a Shannon-Fano code Restrictions include a signal set that strictly belongs in the 'range [1,N]' with 'N = length (dict)'. +@item shannonfanodeco +Returns the original signal that was Shannon-Fano encoded. +@item rleenco +Returns run-length encoded MESSAGE. +@item rledeco +Returns decoded run-length MESSAGE. +@item riceenco +Returns the Rice encoded signal using K or optimal K Default optimal K is chosen between 0-7. +@item ricedeco +Returns the Rice decoded signal vector using CODE and K Compulsory K is need to be specified A restrictions is that a signal set must strictly be non-negative The value of code is a cell array of row-vectors which have the encoded rice value for a single sample. +@item fiboenco +Returns the cell-array of encoded Fibonacci value from the column vectors NUM Universal codes like Fibonacci codes have a useful synchronization property, only for 255 maximum value we have designed these routines. +@item fibodeco +Returns the decoded Fibonacci value from the binary vectors CODE Universal codes like Fibonacci codes have a useful synchronization property, only for 255 maximum value we have designed these routines. +@item fibosplitstream +Returns the split data stream at the word boundaries Assuming the stream was originally encoded using 'fiboenco' and this routine splits the stream at the points where "11" occur together & gives us the code-words which can later be decoded from the 'fibodeco' This however doesn't mean that we intend to verify if all the codewords are correct, and in fact the last symbol in the return list can or can not be a valid codeword +@item golombenco +Returns the Golomb coded signal as cell array Also total length of output code in bits can be obtained This function uses a M need to be supplied for encoding signal vector into a Golomb coded vector. +@item golombdeco +Returns the Golomb decoded signal vector using CODE and M Compulsory m is need to be specified. +@end table +@subsection Block Interleavers +@table @asis +@item intrlv +Interleaved elements of DATA according to ELEMENTS See also: deintrlv +@item helscanintrlv +NROWS-by-NCOLS See also: helscandeintrlv +@item matintrlv +Interleaved elements of DATA with a temporary matrix of size NROWS-by-NCOLS See also: matdeintrlv +@item randintrlv +Interleaves elements of DATA with a random permutation See also: intrlv, deintrlv +@item deintrlv +Restore elements of DATA according to ELEMENTS See also: intrlv +@item matdeintrlv +Restore elements of DATA with a temporary matrix of size NROWS-by-NCOLS See also: matintrlv +@item randdeintrlv +Restore elements of DATA with a random permutation See also: randintrlv, intrlv, deintrlv +@end table +@subsection Block Coding +@table @asis +@item bchdeco +Decodes the coded message CODE using a BCH coder. +@item bchenco +Encodes the message MSG using a [N,K] BCH coding. +@item bchpoly +Calculates the generator polynomials for a BCH coder. +@item convenc +Encode the binary vector MSG with the convolutional encoder described by the trellis structure T +@item cyclgen +Produce the parity check and generator matrix of a cyclic code. +@item cyclpoly +This function returns the cyclic generator polynomials of the code [N,K]. +@item decode +Top level block decoder. +@item encode +Top level block encoder. +@item egolaydec +Decode Extended Golay code +@item egolayenc +Encode with Extended Golay code +@item egolaygen +Extended Golay code generator matrix +@item gen2par +Converts binary generator matrix GEN to the parity check matrix PAR and visa-versa. +@item hammgen +Produce the parity check and generator matrices of a Hamming code. +@item reedmullerdec +Decode the received code word VV using the RM-generator matrix G, of order R, M, returning the code-word C. +@item reedmullerenc +Definition type construction of Reed-Muller code, of order R, length 2^M. +@item reedmullergen +Definition type construction of Reed-Muller code, of order R, length 2^M. +@item rsgenpoly +Creates a generator polynomial for a Reed-Solomon coding with message length of K and codelength of N. +@item rsdec +Decodes the message contained in CODE using a [N,K] Reed-Solomon code. +@item rsdecof +Decodes an ASCII file using a Reed-Solomon coder. +@item rsenc +Encodes the message MSG using a [N,K] Reed-Solomon coding. +@item rsencof +Encodes an ASCII file using a Reed-Solomon coder. +@item systematize +Given G, extract P parity check matrix. +@item syndtable +Create the syndrome decoding table from the parity check matrix H. +@end table +@subsection Modulations +@table @asis +@item ademodce +Baseband demodulator for analog signals. +@item amodce +Baseband modulator for analog signals. +@item ammod +Creates the AM modulation of the amplitude signal X with carrier frequency FC +@item amdemod +Creates the AM demodulation of the signal S sampled at frequency FS with carrier frequency FC +@item apkconst +Plots a ASK/PSK signal constellation. +@item bin2gray +Creates a Gray encoded data Y with the same size as input X +@item demodmap +Demapping of an analog signal to a digital signal. +@item fmmod +Creates the FM modulation S of the message signal M with carrier frequency FC +@item fmdemod +Creates the FM demodulation of the signal S sampled at frequency FS with carrier frequency FC +@item genqammod +Modulates an information sequence of integers X in the range '[0 ... M-1]' onto a quadrature amplitude modulated signal Y, where 'M = length (c) - 1' and C is a 1D vector specifying the signal constellation mapping to be used. +@item genqamdemod +General quadrature amplitude demodulation. +@item modmap +Mapping of a digital signal to an analog signal. +@item pamdemod +Demodulates a pulse amplitude modulated signal X into an information sequence of integers in the range '[0 ... M-1]' PHI controls the initial phase and TYPE controls the constellation mapping. +@item pammod +Modulates an information sequence of integers X in the range '[0 ... M-1]' onto a pulse amplitude modulated signal Y PHI controls the initial phase and TYPE controls the constellation mapping. +@item pskdemod +Demodulates a complex-baseband phase shift keying modulated signal into an information sequence of integers in the range '[0 ... M-1]'. +@item pskmod +Modulates an information sequence of integers X in the range '[0 ... M-1]' onto a complex baseband phase shift keying modulated signal Y. +@item qaskdeco +Demaps an analog signal using a square QASK constellation. +@item qaskenco +Map a digital signal using a square QASK constellation. +@item qammod +Create the QAM modulation of x with a size of alphabet m See also: qamdemod, pskmod, pskdemod +@item qamdemod +Create the QAM demodulation of x with a size of alphabet m See also: qammod, pskmod, pskdemod +@end table +@subsection Channel Filters +@table @asis +@item rcosfir +Implements a cosine filter or root cosine filter impulse response +@end table +@subsection Galois Fields of Even Characteristic +@table @asis +@item + - +Addition and subtraction in a Galois Field. + +@item * / \ +Matrix multiplication and division of Galois arrays. + +@item .* ./ .\ +Element by element multiplication and division of Galois arrays. + +@item ** ^ +Matrix exponentiation of Galois arrays. + +@item .** .^ +Element by element matrix exponentiation of Galois arrays. + +@item ' .' +Matrix transpose of Galois arrays. + +@item == ~= != > >= < <= +Logical operators on Galois arrays. + +@item all +@emph{Not implemented} +@item any +@emph{Not implemented} +@item cosets +Finds the elements of GF(2^M) with primitive polynomial PRIM, that share the same minimum polynomial. +@item conv +Convolve two Galois vectors +@item convmtx +Create matrix to perform repeated convolutions with the same vector in a Galois Field. +@item deconv +Deconvolve two Galois vectors +@item det +Compute the determinant of the Galois array A +@item dftmtx +Form a matrix, that can be used to perform Fourier transforms in a Galois Field +@item diag +Return a diagonal matrix with Galois vector V on diagonal K The second argument is optional. +@item exp +Compute the anti-logarithm for each element of X for a Galois array +@item gf +#endif +@item fft +If X is a column vector, finds the FFT over the primitive element of the Galois Field of X. +@item filter +Digital filtering of vectors in a Galois Field. +@item gftable +This function exists for compatibility with matlab. +@item gfweight +Calculate the minimum weight or distance of a linear block code. +@item ifft +If X is a column vector, finds the IFFT over the primitive element of the Galois Field of X. +@item inv +Compute the inverse of the square matrix A. +@item inverse +See inv +@item isequal +Return true if all of X1, X2, ... are equal See also: isequalwithequalnans +@item log +Compute the natural logarithm for each element of X for a Galois array +@item lu +Compute the LU decomposition of A in a Galois Field. +@item prod +Product of elements along dimension DIM of Galois array. +@item sqrt +Compute the square root of X, element by element, in a Galois Field See also: exp +@item rank +Compute the rank of the Galois array A by counting the independent rows and columns +@item reshape +Return a matrix with M rows and N columns whose elements are taken from the Galois array A. +@item roots +For a vector V with N components, return the roots of the polynomial over a Galois Field +@item sum +Sum of elements along dimension DIM of Galois array. +@item sumsq +Sum of squares of elements along dimension DIM of Galois array If DIM is omitted, it defaults to 1 (column-wise sum of squares) +@item isempty +@emph{Not implemented} +@item isgalois +Return 1 if the value of the expression EXPR is a Galois Field. +@item isprimitive +Returns 1 is the polynomial represented by A is a primitive polynomial of GF(2). +@item length +@emph{Not implemented} +@item minpol +Finds the minimum polynomial for elements of a Galois Field. +@item polyval +@emph{Not implemented} +@item primpoly +Finds the primitive polynomials in GF(2^M). +@item size +@emph{Not implemented} +@end table +@subsection Utility Functions +@table @asis +@item comms +Manual and test code for the Octave Communications toolbox. +@item bi2de +Convert bit matrix to a vector of integers +@item de2bi +Convert a non-negative integer to bit vector +@item oct2dec +Convert octal to decimal values +@item istrellis +Return true if T is a valid trellis structure +@item poly2trellis +Convert convolutional code generator polynomials into trellis form +@item vec2mat +Converts the vector V into a C column matrix with row priority arrangement and with the final column padded with the value D to the correct length. +@item qfunc +Compute the Q function See also: erfc, erf +@item qfuncinv +Compute the inverse Q function See also: erfc, erf +@end table +@subsection Measurement and Analysis +@table @asis +@item berconfint +Returns Bit Error Rate, BER, and confidence interval, INTERVAL, for the number of errors R and number of transmitted bits N with a confidence level of LEVEL. +@item finddelay +Estimate the delay between times series X and time series Y by correlating and finding the peak. +@end table +@end iftex + + +@section Functions Alphabetically +@menu +* ademodce:: Baseband demodulator for analog signals. +* amdemod:: Creates the AM demodulation of the signal S sampled at + frequency FS with carrier frequency FC +* ammod:: Creates the AM modulation of the amplitude signal X with + carrier frequency FC +* amodce:: Baseband modulator for analog signals. +* apkconst:: Plots a ASK/PSK signal constellation. +* awgn:: Add white Gaussian noise to a voltage signal +* bchdeco:: Decodes the coded message CODE using a BCH coder. +* bchenco:: Encodes the message MSG using a [N,K] BCH coding. +* bchpoly:: Calculates the generator polynomials for a BCH coder. +* berconfint:: Returns Bit Error Rate, BER, and confidence interval, + INTERVAL, for the number of errors R and number of + transmitted bits N with a confidence level of LEVEL. +* bi2de:: Convert bit matrix to a vector of integers +* bin2gray:: Creates a Gray encoded data Y with the same size as input X +* biterr:: Compares two matrices and returns the number of bit errors + and the bit error rate. +* bsc:: Send DATA into a binary symmetric channel with probability + P of error one each symbol +* comms:: Manual and test code for the Octave Communications toolbox. +* compand:: Compresses and expanding the dynamic range of a signal + using a mu-law or or A-law algorithm +* conv:: Convolve two Galois vectors +* convenc:: Encode the binary vector MSG with the convolutional encoder + described by the trellis structure T +* convmtx:: Create matrix to perform repeated convolutions with the + same vector in a Galois Field. +* cosets:: Finds the elements of GF(2^M) with primitive polynomial + PRIM, that share the same minimum polynomial. +* cyclgen:: Produce the parity check and generator matrix of a cyclic + code. +* cyclpoly:: This function returns the cyclic generator polynomials of + the code [N,K]. +* de2bi:: Convert a non-negative integer to bit vector +* decode:: Top level block decoder. +* deconv:: Deconvolve two Galois vectors +* deintrlv:: Restore elements of DATA according to ELEMENTS See also: + intrlv +* demodmap:: Demapping of an analog signal to a digital signal. +* det:: Compute the determinant of the Galois array A +* dftmtx:: Form a matrix, that can be used to perform Fourier + transforms in a Galois Field +* diag:: Return a diagonal matrix with Galois vector V on diagonal K + The second argument is optional. +* dpcmdeco:: Decode using differential pulse code modulation (DPCM) +* dpcmenco:: Encode using differential pulse code modulation (DPCM) +* dpcmopt:: Optimize the DPCM parameters and codebook +* egolaydec:: Decode Extended Golay code +* egolayenc:: Encode with Extended Golay code +* egolaygen:: Extended Golay code generator matrix +* encode:: Top level block encoder. +* exp:: Compute the anti-logarithm for each element of X for a + Galois array +* eyediagram:: Plot the eye-diagram of a signal. +* fft:: If X is a column vector, finds the FFT over the primitive + element of the Galois Field of X. +* fibodeco:: Returns the decoded Fibonacci value from the binary vectors + CODE Universal codes like Fibonacci codes have a useful + synchronization property, only for 255 maximum value we + have designed these routines. +* fiboenco:: Returns the cell-array of encoded Fibonacci value from the + column vectors NUM Universal codes like Fibonacci codes + have a useful synchronization property, only for 255 + maximum value we have designed these routines. +* fibosplitstream:: Returns the split data stream at the word boundaries + Assuming the stream was originally encoded using 'fiboenco' + and this routine splits the stream at the points where "11" + occur together & gives us the code-words which can later be + decoded from the 'fibodeco' This however doesn't mean that + we intend to verify if all the codewords are correct, and + in fact the last symbol in the return list can or can not + be a valid codeword +* filter:: Digital filtering of vectors in a Galois Field. +* finddelay:: Estimate the delay between times series X and time series Y + by correlating and finding the peak. +* fmdemod:: Creates the FM demodulation of the signal S sampled at + frequency FS with carrier frequency FC +* fmmod:: Creates the FM modulation S of the message signal M with + carrier frequency FC +* gen2par:: Converts binary generator matrix GEN to the parity check + matrix PAR and visa-versa. +* genqamdemod:: General quadrature amplitude demodulation. +* genqammod:: Modulates an information sequence of integers X in the + range '[0 ... M-1]' onto a quadrature amplitude modulated + signal Y, where 'M = length (c) - 1' and C is a 1D vector + specifying the signal constellation mapping to be used. +* gf:: #endif +* gftable:: This function exists for compatibility with matlab. +* gfweight:: Calculate the minimum weight or distance of a linear block + code. +* golombdeco:: Returns the Golomb decoded signal vector using CODE and M + Compulsory m is need to be specified. +* golombenco:: Returns the Golomb coded signal as cell array Also total + length of output code in bits can be obtained This function + uses a M need to be supplied for encoding signal vector + into a Golomb coded vector. +* hammgen:: Produce the parity check and generator matrices of a + Hamming code. +* helscanintrlv:: NROWS-by-NCOLS See also: helscandeintrlv +* huffmandeco:: Decode signal encoded by 'huffmanenco' +* huffmandict:: Builds a Huffman code, given a probability list. +* huffmanenco:: Returns the Huffman encoded signal using DICT. +* ifft:: If X is a column vector, finds the IFFT over the primitive + element of the Galois Field of X. +* intrlv:: Interleaved elements of DATA according to ELEMENTS See + also: deintrlv +* inv:: Compute the inverse of the square matrix A. +* inverse:: See inv +* isequal:: Return true if all of X1, X2, ... are equal See also: + isequalwithequalnans +* isgalois:: Return 1 if the value of the expression EXPR is a Galois + Field. +* isprimitive:: Returns 1 is the polynomial represented by A is a primitive + polynomial of GF(2). +* istrellis:: Return true if T is a valid trellis structure +* lloyds:: Optimize the quantization table and codes to reduce + distortion. +* log:: Compute the natural logarithm for each element of X for a + Galois array +* lu:: Compute the LU decomposition of A in a Galois Field. +* lz77deco:: Lempel-Ziv 77 source algorithm decoding implementation. +* lz77enco:: Lempel-Ziv 77 source algorithm implementation. +* matdeintrlv:: Restore elements of DATA with a temporary matrix of size + NROWS-by-NCOLS See also: matintrlv +* matintrlv:: Interleaved elements of DATA with a temporary matrix of + size NROWS-by-NCOLS See also: matdeintrlv +* minpol:: Finds the minimum polynomial for elements of a Galois + Field. +* modmap:: Mapping of a digital signal to an analog signal. +* oct2dec:: Convert octal to decimal values +* pamdemod:: Demodulates a pulse amplitude modulated signal X into an + information sequence of integers in the range '[0 ... M-1]' + PHI controls the initial phase and TYPE controls the + constellation mapping. +* pammod:: Modulates an information sequence of integers X in the + range '[0 ... M-1]' onto a pulse amplitude modulated signal + Y PHI controls the initial phase and TYPE controls the + constellation mapping. +* poly2trellis:: Convert convolutional code generator polynomials into + trellis form +* primpoly:: Finds the primitive polynomials in GF(2^M). +* prod:: Product of elements along dimension DIM of Galois array. +* pskdemod:: Demodulates a complex-baseband phase shift keying modulated + signal into an information sequence of integers in the + range '[0 ... M-1]'. +* pskmod:: Modulates an information sequence of integers X in the + range '[0 ... M-1]' onto a complex baseband phase shift + keying modulated signal Y. +* qamdemod:: Create the QAM demodulation of x with a size of alphabet m + See also: qammod, pskmod, pskdemod +* qammod:: Create the QAM modulation of x with a size of alphabet m + See also: qamdemod, pskmod, pskdemod +* qaskdeco:: Demaps an analog signal using a square QASK constellation. +* qaskenco:: Map a digital signal using a square QASK constellation. +* qfunc:: Compute the Q function See also: erfc, erf +* qfuncinv:: Compute the inverse Q function See also: erfc, erf +* quantiz:: Quantization of an arbitrary signal relative to a + partitioning +* randdeintrlv:: Restore elements of DATA with a random permutation See + also: randintrlv, intrlv, deintrlv +* randerr:: Generate a matrix of random bit errors. +* randint:: Generate a matrix of random binary numbers. +* randintrlv:: Interleaves elements of DATA with a random permutation See + also: intrlv, deintrlv +* randsrc:: Generate a matrix of random symbols. +* rank:: Compute the rank of the Galois array A by counting the + independent rows and columns +* rcosfir:: Implements a cosine filter or root cosine filter impulse + response +* reedmullerdec:: Decode the received code word VV using the RM-generator + matrix G, of order R, M, returning the code-word C. +* reedmullerenc:: Definition type construction of Reed-Muller code, of + order R, length 2^M. +* reedmullergen:: Definition type construction of Reed-Muller code, of + order R, length 2^M. +* reshape:: Return a matrix with M rows and N columns whose elements + are taken from the Galois array A. +* ricedeco:: Returns the Rice decoded signal vector using CODE and K + Compulsory K is need to be specified A restrictions is that + a signal set must strictly be non-negative The value of + code is a cell array of row-vectors which have the encoded + rice value for a single sample. +* riceenco:: Returns the Rice encoded signal using K or optimal K + Default optimal K is chosen between 0-7. +* rledeco:: Returns decoded run-length MESSAGE. +* rleenco:: Returns run-length encoded MESSAGE. +* roots:: For a vector V with N components, return the roots of the + polynomial over a Galois Field +* rsdec:: Decodes the message contained in CODE using a [N,K] + Reed-Solomon code. +* rsdecof:: Decodes an ASCII file using a Reed-Solomon coder. +* rsenc:: Encodes the message MSG using a [N,K] Reed-Solomon coding. +* rsencof:: Encodes an ASCII file using a Reed-Solomon coder. +* rsgenpoly:: Creates a generator polynomial for a Reed-Solomon coding + with message length of K and codelength of N. +* scatterplot:: Display the scatter plot of a signal. +* shannonfanodeco:: Returns the original signal that was Shannon-Fano + encoded. +* shannonfanodict:: Returns the code dictionary for source using + Shannon-Fano algorithm Dictionary is built from + SYMBOL_PROBABILITIES using the Shannon-Fano scheme. +* shannonfanoenco:: Returns the Shannon-Fano encoded signal using DICT This + function uses a DICT built from the 'shannonfanodict' and + uses it to encode a signal list into a Shannon-Fano code + Restrictions include a signal set that strictly belongs in + the 'range [1,N]' with 'N = length (dict)'. +* sqrt:: Compute the square root of X, element by element, in a + Galois Field See also: exp +* sum:: Sum of elements along dimension DIM of Galois array. +* sumsq:: Sum of squares of elements along dimension DIM of Galois + array If DIM is omitted, it defaults to 1 (column-wise sum + of squares) +* symerr:: Compares two matrices and returns the number of symbol + errors and the symbol error rate. +* syndtable:: Create the syndrome decoding table from the parity check + matrix H. +* systematize:: Given G, extract P parity check matrix. +* vec2mat:: Converts the vector V into a C column matrix with row + priority arrangement and with the final column padded with + the value D to the correct length. +* wgn:: Returns a M-by-N matrix Y of white Gaussian noise. +@end menu + +@node ademodce, amdemod, , Function Reference +@subsection ademodce + +@deftypefn {Function File} {@var{y} =} ademodce (@var{x}, @var{Fs}, "amdsb-tc", offset) +@deftypefnx {Function File} {@var{y} =} ademodce (@var{x}, @var{Fs}, "amdsb-tc/costas", offset) +@deftypefnx {Function File} {@var{y} =} ademodce (@var{x}, @var{Fs}, "amdsb-sc") +@deftypefnx {Function File} {@var{y} =} ademodce (@var{x}, @var{Fs}, "amdsb-sc/costas") +@deftypefnx {Function File} {@var{y} =} ademodce (@var{x}, @var{Fs}, "amssb") +@deftypefnx {Function File} {@var{y} =} ademodce (@var{x}, @var{Fs}, "qam") +@deftypefnx {Function File} {@var{y} =} ademodce (@var{x}, @var{Fs}, "qam/cmplx") +@deftypefnx {Function File} {@var{y} =} ademodce (@var{x}, @var{Fs}, "fm", @var{dev}) +@deftypefnx {Function File} {@var{y} =} ademodce (@var{x}, @var{Fs}, "pm", @var{dev}) +@deftypefnx {Function File} {@var{y} =} ademodce (@var{x}, [@var{Fs}, @var{iphs}], @dots{}) +@deftypefnx {Function File} {@var{y} =} ademodce (@dots{}, @var{num}, @var{den}) + +Baseband demodulator for analog signals. The input signal is specified by +@var{x}, its sampling frequency by @var{Fs} and the type of modulation +by the third argument, @var{typ}. The default values of @var{Fs} is 1 and +@var{typ} is "amdsb-tc" + +If the argument @var{Fs} is a two element vector, the first element +represents the sampling rate and the second the initial phase + +The different types of demodulations that are available are + +@table @asis +@item "am" +@itemx "amdsb-tc" +Double-sideband with carrier +@item "amdsb-tc/costas" +Double-sideband with carrier and Costas phase locked loop +@item "amdsb-sc" +Double-sideband with suppressed carrier +@item "amssb" +Single-sideband with frequency domain Hilbert filtering +@item "qam" +Quadrature amplitude demodulation. In-phase in odd-columns and quadrature +in even-columns +@item "qam/cmplx" +Quadrature amplitude demodulation with complex return value +@item "fm" +Frequency demodulation +@item "pm" +Phase demodulation +@end table + +Additional arguments are available for the demodulations "amdsb-tc", "fm", +"pm". These arguments are + +@table @code +@item offset +The offset in the input signal for the transmitted carrier +@item dev +The deviation of the phase and frequency modulation +@end table + +It is possible to specify a low-pass filter, by the numerator @var{num} +and denominator @var{den} that will be applied to the returned vector + +See also: ademodce, dmodce +@end deftypefn + + + +@node amdemod, ammod, ademodce, Function Reference +@subsection amdemod + +@deftypefn {Function File} {@var{m} =} amdemod (@var{s}, @var{fc}, @var{fs}) +Creates the AM demodulation of the signal @var{s} +sampled at frequency @var{fs} with carrier frequency @var{fc} + +Inputs: +@itemize +@item +@var{s}: AM modulated signal + +@item +@var{fc}: carrier frequency + +@item +@var{fs}: sampling frequency +@end itemize + +Output: +@itemize +@item +@var{m}: AM demodulation of the signal +@end itemize + +Demo +@example +demo amdemod +@end example +See also: ammod, fmmod, fmdemod +@end deftypefn + + + +@node ammod, amodce, amdemod, Function Reference +@subsection ammod + +@deftypefn {Function File} {@var{y} =} ammod (@var{x}, @var{fc}, @var{fs}) +Creates the AM modulation of the amplitude signal @var{x} +with carrier frequency @var{fc} + +Inputs: +@itemize +@item +@var{x}: amplitude message signal + +@item +@var{fc}: carrier frequency + +@item +@var{fs}: sampling frequency +@end itemize + +Output: +@itemize +@var{y}: The AM modulation of @var{x} +@end itemize +Demo +@example +demo ammod +@end example +See also: amdemod, fmmod, fmdemod +@end deftypefn + + + +@node amodce, apkconst, ammod, Function Reference +@subsection amodce + +@deftypefn {Function File} {@var{y} =} amodce (@var{x}, @var{Fs}, "amdsb-tc", offset) +@deftypefnx {Function File} {@var{y} =} amodce (@var{x}, @var{Fs}, "amdsb-sc") +@deftypefnx {Function File} {@var{y} =} amodce (@var{x}, @var{Fs}, "amssb") +@deftypefnx {Function File} {@var{y} =} amodce (@var{x}, @var{Fs}, "amssb/time", @var{num}, @var{den}) +@deftypefnx {Function File} {@var{y} =} amodce (@var{x}, @var{Fs}, "qam") +@deftypefnx {Function File} {@var{y} =} amodce (@var{x}, @var{Fs}, "fm", @var{dev}) +@deftypefnx {Function File} {@var{y} =} amodce (@var{x}, @var{Fs}, "pm", @var{dev}) +@deftypefnx {Function File} {@var{y} =} amodce (@var{x}, [@var{Fs}, @var{iphs}], @dots{}) + +Baseband modulator for analog signals. The input signal is specified by +@var{x}, its sampling frequency by @var{Fs} and the type of modulation +by the third argument, @var{typ}. The default values of @var{Fs} is 1 and +@var{typ} is "amdsb-tc" + +If the argument @var{Fs} is a two element vector, the first element +represents the sampling rate and the second the initial phase + +The different types of modulations that are available are + +@table @asis +@item "am" +@itemx "amdsb-tc" +Double-sideband with carrier +@item "amdsb-sc" +Double-sideband with suppressed carrier +@item "amssb" +Single-sideband with frequency domain Hilbert filtering +@item "amssb/time" +Single-sideband with time domain filtering. Hilbert filter is used by +default, but the filter can be specified +@item "qam" +Quadrature amplitude modulation +@item "fm" +Frequency modulation +@item "pm" +Phase modulation +@end table + +Additional arguments are available for the modulations "amdsb-tc", "fm", +"pm" and "amssb/time". These arguments are + +@table @code +@item offset +The offset in the input signal for the transmitted carrier +@item dev +The deviation of the phase and frequency modulation +@item num +@itemx den +The numerator and denominator of the filter transfer function for the +time domain filtering of the SSB modulation +@end table + +See also: ademodce, dmodce +@end deftypefn + + + +@node apkconst, awgn, amodce, Function Reference +@subsection apkconst + +@deftypefn {Function File} {} apkconst (@var{nsig}) +@deftypefnx {Function File} {} apkconst (@var{nsig}, @var{amp}) +@deftypefnx {Function File} {} apkconst (@var{nsig}, @var{amp}, @var{phs}) +@deftypefnx {Function File} {} apkconst (@dots{}, "n") +@deftypefnx {Function File} {} apkconst (@dots{}, @var{str}) +@deftypefnx {Function File} {@var{y} =} apkconst (@dots{}) + +Plots a ASK/PSK signal constellation. Argument @var{nsig} is a real vector +whose length determines the number of ASK radii in the constellation +The values of vector @var{nsig} determine the number of points in each +ASK radii + +By default the radii of each ASK modulated level is given by the index of +@var{nsig}. The amplitudes can be defined explicitly in the variable +@var{amp}, which is a vector of the same length as @var{nsig} + +By default the first point in each ASK radii has zero phase, and following +points are coding in an anti-clockwise manner. If @var{phs} is defined then +it is a vector of the same length as @var{nsig} defining the initial phase +in each ASK radii + +In addition @code{apkconst} takes two string arguments "n" and @var{str} +If the string "n" is included in the arguments, then a number is printed +next to each constellation point giving the symbol value that would be +mapped to this point by the @code{modmap} function. The argument @var{str} +is a plot style string (example "r+") and determines the default gnuplot +point style to use for plot points in the constellation + +If @code{apkconst} is called with a return argument, then no plot is +created. However the return value is a vector giving the in-phase and +quadrature values of the symbols in the constellation +See also: dmod, ddemod, modmap, demodmap +@end deftypefn + + + +@node awgn, bchdeco, apkconst, Function Reference +@subsection awgn + +@deftypefn {Function File} {@var{y} =} awgn (@var{x}, @var{snr}) +@deftypefnx {Function File} {@var{y} =} awgn (@var{x}, @var{snr}, @var{pwr}) +@deftypefnx {Function File} {@var{y} =} awgn (@var{x}, @var{snr}, @var{pwr}, @var{seed}) +@deftypefnx {Function File} {@var{y} =} awgn (@dots{}, @var{type}) + +Add white Gaussian noise to a voltage signal + +The input @var{x} is assumed to be a real or complex voltage signal. The +returned value @var{y} will be the same form and size as @var{x} but with +Gaussian noise added. Unless the power is specified in @var{pwr}, the +signal power is assumed to be 0dBW, and the noise of @var{snr} dB will be +added with respect to this. If @var{pwr} is a numeric value then the signal +@var{x} is assumed to be @var{pwr} dBW, otherwise if @var{pwr} is +"measured", then the power in the signal will be measured and the noise +added relative to this measured power + +If @var{seed} is specified, then the random number generator seed is +initialized with this value + +By default the @var{snr} and @var{pwr} are assumed to be in dB and dBW +respectively. This default behavior can be chosen with @var{type} +set to "dB". In the case where @var{type} is set to "linear", @var{pwr} +is assumed to be in Watts and @var{snr} is a ratio +See also: randn, wgn +@end deftypefn + + + +@node bchdeco, bchenco, awgn, Function Reference +@subsection bchdeco + +@deftypefn {Loadable Function} {@var{msg} =} bchdeco (@var{code}, @var{k}, @var{t}) +@deftypefnx {Loadable Function} {@var{msg} =} bchdeco (@var{code}, @var{k}, @var{t}, @var{prim}) +@deftypefnx {Loadable Function} {@var{msg} =} bchdeco (@dots{}, @var{parpos}) +@deftypefnx {Loadable Function} {[@var{msg}, @var{err}] =} bchdeco (@dots{}) +@deftypefnx {Loadable Function} {[@var{msg}, @var{err}, @var{ccode}] =} bchdeco (@dots{}) +Decodes the coded message @var{code} using a BCH coder. The message length +of the coder is defined in variable @var{k}, and the error correction +capability of the code is defined in @var{t}. + +The variable @var{code} is a binary array with @var{n} columns and an +arbitrary number of rows. Each row of @var{code} represents a single symbol +to be decoded by the BCH coder. The decoded message is returned in the +binary array @var{msg} containing @var{k} columns and the same number of +rows as @var{code}. + +The use of @code{bchdeco} can be seen in the following short example. + +@example +m = 3; n = 2^m -1; k = 4; t = 1; +msg = randint (10, k); +code = bchenco (msg, n, k); +noisy = mod (randerr (10,n) + code, 2); +[dec, err] = bchdeco (msg, k, t); +@end example + +Valid codes can be found using @code{bchpoly}. In general the codeword +length @var{n} should be of the form @code{2^@var{m}-1}, where m is an +integer. However, shortened BCH codes can be used such that if +@code{[2^@var{m}-1,@var{k}]} is a valid code +@code{[2^@var{m}-1-@var{x},@var{k}-@var{x}]} + is also a valid code using +the same generator polynomial. + +By default the BCH coding is based on the properties of the Galois +Field GF(2^@var{m}). The primitive polynomial used in the Galois +can be overridden by a primitive polynomial in @var{prim}. Suitable +primitive polynomials can be constructed with @code{primpoly}. The form +of @var{prim} maybe be either a integer representation of the primitive +polynomial as given by @code{primpoly}, or a binary representation that +might be constructed like + +@example +m = 3; +prim = de2bi (primpoly (m)); +@end example + +By default the parity symbols are assumed to be placed at the beginning of +the coded message. The variable @var{parpos} controls this positioning and +can take the values @code{"beginning\"} or @code{\"end\"}. +See also: bchpoly, bchenco, decode, primpoly +@end deftypefn + + + +@node bchenco, bchpoly, bchdeco, Function Reference +@subsection bchenco + +@deftypefn {Loadable Function} {@var{code} =} bchenco (@var{msg}, @var{n}, @var{k}) +@deftypefnx {Loadable Function} {@var{code} =} bchenco (@var{msg}, @var{n}, @var{k}, @var{g}) +@deftypefnx {Loadable Function} {@var{code} =} bchenco (@dots{}, @var{parpos}) +Encodes the message @var{msg} using a [@var{n},@var{k}] BCH coding. +The variable @var{msg} is a binary array with @var{k} columns and an +arbitrary number of rows. Each row of @var{msg} represents a single symbol +to be coded by the BCH coder. The coded message is returned in the binary +array @var{code} containing @var{n} columns and the same number of rows as +@var{msg}. + +The use of @code{bchenco} can be seen in the following short example. + +@example +m = 3; n = 2^m -1; k = 4; +msg = randint (10,k); +code = bchenco (msg, n, k); +@end example + +Valid codes can be found using @code{bchpoly}. In general the codeword +length @var{n} should be of the form @code{2^@var{m}-1}, where m is an +integer. However, shortened BCH codes can be used such that if +@code{[2^@var{m}-1,@var{k}]} is a valid code +@code{[2^@var{m}-1-@var{x},@var{k}-@var{x}]} + is also a valid code using +the same generator polynomial. + +By default the generator polynomial used in the BCH coding is +based on the properties of the Galois Field GF(2^@var{m}). This +default generator polynomial can be overridden by a polynomial in @var{g}. +Suitable generator polynomials can be constructed with @code{bchpoly}. + +By default the parity symbols are placed at the beginning of the coded +message. The variable @var{parpos} controls this positioning and can take +the values @code{"beginning\"} or @code{\"end\"}. +See also: bchpoly, bchdeco, encode +@end deftypefn + + + +@node bchpoly, berconfint, bchenco, Function Reference +@subsection bchpoly + +@deftypefn {Function File} {@var{p} =} bchpoly () +@deftypefnx {Function File} {@var{p} =} bchpoly (@var{n}) +@deftypefnx {Function File} {@var{p} =} bchpoly (@var{n}, @var{k}) +@deftypefnx {Function File} {@var{p} =} bchpoly (@var{prim}, @var{k}) +@deftypefnx {Function File} {@var{p} =} bchpoly (@var{n}, @var{k}, @var{prim}) +@deftypefnx {Function File} {@var{p} =} bchpoly (@dots{}, @var{probe}) +@deftypefnx {Function File} {[@var{p}, @var{f}] =} bchpoly (@dots{}) +@deftypefnx {Function File} {[@var{p}, @var{f}, @var{c}] =} bchpoly (@dots{}) +@deftypefnx {Function File} {[@var{p}, @var{f}, @var{c}, @var{par}] =} bchpoly (@dots{}) +@deftypefnx {Function File} {[@var{p}, @var{f}, @var{c}, @var{par}, @var{t}] =} bchpoly (@dots{}) + +Calculates the generator polynomials for a BCH coder. Called with no input +arguments @code{bchpoly} returns a list of all of the valid BCH codes for +the codeword length 7, 15, 31, 63, 127, 255 and 511. A three column matrix +is returned with each row representing a separate valid BCH code. The first +column is the codeword length, the second the message length and the third +the error correction capability of the code + +Called with a single input argument, @code{bchpoly} returns the valid BCH +codes for the specified codeword length @var{n}. The output format is the +same as above + +When called with two or more arguments, @code{bchpoly} calculates the +generator polynomial of a particular BCH code. The generator polynomial +is returned in @var{p} as a vector representation of a polynomial in +GF(2). The terms of the polynomial are listed least-significant term +first + +The desired BCH code can be specified by its codeword length @var{n} +and its message length @var{k}. Alternatively, the primitive polynomial +over which to calculate the polynomial can be specified as @var{prim} +If a vector representation of the primitive polynomial is given, then +@var{prim} can be specified as the first argument of two arguments, +or as the third argument. However, if an integer representation of the +primitive polynomial is used, then the primitive polynomial must be +specified as the third argument + +When called with two or more arguments, @code{bchpoly} can also return the +factors @var{f} of the generator polynomial @var{p}, the cyclotomic coset +for the Galois field over which the BCH code is calculated, the parity +check matrix @var{par} and the error correction capability @var{t}. It +should be noted that the parity check matrix is calculated with +@code{cyclgen} and limitations in this function means that the parity +check matrix is only available for codeword length up to 63. For +codeword length longer than this @var{par} returns an empty matrix + +With a string argument @var{probe} defined, the action of @code{bchpoly} +is to calculate the error correcting capability of the BCH code defined +by @var{n}, @var{k} and @var{prim} and return it in @var{p}. This is +similar to a call to @code{bchpoly} with zero or one argument, except that +only a single code is checked. Any string value for @var{probe} will +force this action + +In general the codeword length @var{n} can be expressed as +@code{2^@var{m}-1}, where @var{m} is an integer. However, if +[@var{n},@var{k}] is a valid BCH code, then a shortened BCH code of +the form [@var{n}-@var{x},@var{k}-@var{x}] can be created with the +same generator polynomial + +See also: cyclpoly, encode, decode, cosets +@end deftypefn + + + +@node berconfint, bi2de, bchpoly, Function Reference +@subsection berconfint + +@deftypefn {Function File} {@var{ber} =} berconfint (@var{r}, @var{n}) +@deftypefnx {Function File} {[@var{ber}, @var{interval}] =} berconfint (@var{r}, @var{n}) +@deftypefnx {Function File} {[@var{ber}, @var{interval}] =} berconfint (@var{r}, @var{n}, @var{level}) + +Returns Bit Error Rate, @var{ber}, and confidence interval, @var{interval}, for +the number of errors @var{r} and number of transmitted bits @var{n} with a +confidence level of @var{level}. By default @var{level} is 0.95 + +The confidence interval is the Wilson one (without continuity correction) for a proportion. By contrast, Matlab appears to return the Clopper–Pearson confidence interval + +Reference: + Robert G. Newcombe (1998), "Two‐sided confidence intervals for the single proportion: comparison of seven methods", Statistics in Medicine 17(8):857-872 +@end deftypefn + + + +@node bi2de, bin2gray, berconfint, Function Reference +@subsection bi2de + +@deftypefn {Function File} {@var{d} =} bi2de (@var{b}) +@deftypefnx {Function File} {@var{d} =} bi2de (@var{b}, @var{f}) +@deftypefnx {Function File} {@var{d} =} bi2de (@var{b}, @var{p}) +@deftypefnx {Function File} {@var{d} =} bi2de (@var{b}, @var{p}, @var{f}) + +Convert bit matrix to a vector of integers + +Each row of the matrix @var{b} is treated as a single integer represented +in binary form. The elements of @var{b}, must therefore be '0' or '1' + +If @var{p} is defined then it is treated as the base of the decomposition +and the elements of @var{b} must then lie between '0' and 'p-1' + +The variable @var{f} defines whether the first or last element of @var{b} +is considered to be the most-significant. Valid values of @var{f} are +"right-msb" or "left-msb". By default @var{f} is "right-msb" + +See also: de2bi +@end deftypefn + + + +@node bin2gray, biterr, bi2de, Function Reference +@subsection bin2gray + +@deftypefn {Function File} {[@var{y}, @var{mapping}] =} bin2gray (@var{x}, @var{type}, @var{M}) +Creates a Gray encoded data @var{y} with the same size as input @var{x} + +Input: +@itemize +@item @var{x} Binary matrix data + +@item @var{type}: The modulation type +choices available:'qam', 'pam','psk','dpsk', and 'fsk' + +@item @var{M}: The modualtion order must be a power of 2 +@end itemize + +Output: +@itemize +@item @var{y}: The gray data of the @var{x} data +@item @var{mapping}: This provides the gray labesfor the given modulation +@end itemize + +Example +@example +y = bin2gray ([0:3], 'qam', 16) +y = + + 0 + 1 + 3 + 2 +@end example + +Example with matrix +@example +y = bin2gray ([0:3; 12:15], 'qam', 16) +y = + + 0 1 3 2 + 8 9 11 10 +@end example +See also: qammod +@end deftypefn + + + +@node biterr, bsc, bin2gray, Function Reference +@subsection biterr + +@deftypefn {Function File} {[@var{num}, @var{rate}] =} biterr (@var{a}, @var{b}) +@deftypefnx {Function File} {[@var{num}, @var{rate}] =} biterr (@dots{}, @var{k}) +@deftypefnx {Function File} {[@var{num}, @var{rate}] =} biterr (@dots{}, @var{flag}) +@deftypefnx {Function File} {[@var{num}, @var{rate} @var{ind}] =} biterr (@dots{}) + +Compares two matrices and returns the number of bit errors and the bit +error rate. The binary representations of the variables @var{a} and +@var{b} are treated and @var{a} and @var{b} can be either: + +@table @asis +@item Both matrices +In this case both matrices must be the same size and then by default the +return values @var{num} and @var{rate} are the overall number of bit +errors and the overall bit error rate +@item One column vector +In this case the column vector is used for bit error comparison column-wise +with the matrix. The returned values @var{num} and @var{rate} are then +row vectors containing the number of bit errors and the bit error rate for +each of the column-wise comparisons. The number of rows in the matrix +must be the same as the length of the column vector +@item One row vector +In this case the row vector is used for bit error comparison row-wise +with the matrix. The returned values @var{num} and @var{rate} are then +column vectors containing the number of bit errors and the bit error rate +for each of the row-wise comparisons. The number of columns in the matrix +must be the same as the length of the row vector +@end table + +This behavior can be overridden with the variable @var{flag}. @var{flag} +can take the value "column-wise", "row-wise" or "overall". A column-wise +comparison is not possible with a row vector and visa-versa + +By default the number of bits in each symbol is assumed to be give by the +number required to represent the maximum value of @var{a} and @var{b} +The number of bits to represent a symbol can be overridden by the variable +@var{k} +@end deftypefn + + + +@node bsc, comms, biterr, Function Reference +@subsection bsc + +@deftypefn {Function File} {@var{y} =} bsc (@var{data}, @var{p}) +Send @var{data} into a binary symmetric channel with probability +@var{p} of error one each symbol +@end deftypefn + + + +@node comms, compand, bsc, Function Reference +@subsection comms + +@deftypefn {Function File} {} comms ("help") +@deftypefnx {Function File} {} comms ("info") +@deftypefnx {Function File} {} comms ("info", @var{mod}) +@deftypefnx {Function File} {} comms ("test") +@deftypefnx {Function File} {} comms ("test", @var{mod}) + +Manual and test code for the Octave Communications toolbox. There are +5 possible ways to call this function + +@table @code +@item comms ("help") +Display this help message. Called with no arguments, this function also +displays this help message +@item comms ("info") +Open the Communications toolbox manual +@item comms ("info", @var{mod}) +Open the Communications toolbox manual at the section specified by +@var{mod} +@item comms ("test") +Run all of the test code for the Communications toolbox +@item comms ("test", @var{mod}) +Run only the test code for the Communications toolbox in the module +@var{mod} +@end table + +Valid values for the variable @var{mod} are + +@table @asis +@item "all" +All of the toolbox +@item "random" +The random signal generation and analysis package +@item "source" +The source coding functions of the package +@item "block" +The block coding functions +@item "convol" +The convolution coding package +@item "modulation" +The modulation package +@item "special" +The special filter functions +@item "galois" +The Galois fields package +@end table + +Please note that this function file should be used as an example of the +use of this toolbox +@end deftypefn + + + +@node compand, conv, comms, Function Reference +@subsection compand + +@deftypefn {Function File} {@var{y} =} compand (@var{x}, @var{mu}, @var{V}, "mu/compressor") +@deftypefnx {Function File} {@var{y} =} compand (@var{x}, @var{mu}, @var{V}, "mu/expander") +@deftypefnx {Function File} {@var{y} =} compand (@var{x}, @var{mu}, @var{V}, "A/compressor") +@deftypefnx {Function File} {@var{y} =} compand (@var{x}, @var{mu}, @var{V}, "A/expander") + +Compresses and expanding the dynamic range of a signal using a mu-law or +or A-law algorithm + +The mu-law compressor/expander for reducing the dynamic range, is used +if the fourth argument of @code{compand} starts with "mu/". Whereas the +A-law compressor/expander is used if @code{compand} starts with "A/" +The mu-law algorithm uses the formulation + +@tex +$$ +y = {V log (1 + \mu / V \|x\|) \over log (1 + \mu)} sgn(x) +$$ +@end tex +@ifnottex +@example +@group + + V log (1 + \mu/V |x|) + y = -------------------- sgn(x) + log (1 + \mu) + +@end group +@end example +@end ifnottex + +while the A-law algorithm used the formulation + +@tex +$$ +y = { \left\{ \matrix{ {A / (1 + log A) x}, & 0 <= \|x\| <= V/A \cr + & \cr + {V log (1 + log(A/V \|x\|) ) \over 1 + logA}, & + V/A < \|x\| <= V} \right. } +$$ +@end tex +@ifnottex +@example +@group + + / A / (1 + log A) x, 0 <= |x| <= V/A + | + y = < V ( 1 + log (A/V |x|) ) + | ----------------------- sgn(x), V/A < |x| <= V + \ 1 + log A +@end group +@end example +@end ifnottex + +Neither converts from or to audio file ulaw format. Use mu2lin or lin2mu +instead + +See also: m2ulin, lin2mu +@end deftypefn + + + +@node conv, convenc, compand, Function Reference +@subsection conv + +@deftypefn {Function File} {} conv (@var{a}, @var{b}) +Convolve two Galois vectors + +@code{y = conv (a, b)} returns a vector of length equal to +@code{length (a) + length (b) - 1} +If @var{a} and @var{b} are polynomial coefficient vectors, @code{conv} +returns the coefficients of the product polynomial +See also: deconv +@end deftypefn + + + +@node convenc, convmtx, conv, Function Reference +@subsection convenc + +@deftypefn {Function File} {@var{y} =} convenc (@var{msg}, @var{t}) +@deftypefnx {Function File} {@var{y} =} convenc (@var{msg}, @var{t}, @var{punct}) +@deftypefnx {Function File} {@var{y} =} convenc (@var{msg}, @var{t}, @var{punct}, @var{s0}) +@deftypefnx {Function File} {[@var{y}, @var{state_end}] =} convenc (@dots{}) +Encode the binary vector @var{msg} with the convolutional encoder +described by the trellis structure @var{t} + +The rate @math{k/n} convolutional encoder encodes @math{k} bits at a +time from the input vector and produces @math{n} bits at a time into the +output vector. The input @var{msg} must have a length that is a multiple +of @math{k} + +If the initial state @var{s0} is specified, it indicates the internal +state of the encoder when the first @math{k} input bits are fed in. The +default value of @var{s0} is 0 + +The optional output argument @var{state_end} indicates the internal state +of the encoder after the last bits are encoded. This allows the state of +the encoder to be saved and applied to the next call to @code{convenc} to +process data in blocks + +See also: poly2trellis +@end deftypefn + + + +@node convmtx, cosets, convenc, Function Reference +@subsection convmtx + +@deftypefn {Function File} {} convmtx (@var{a}, @var{n}) + +Create matrix to perform repeated convolutions with the same vector +in a Galois Field. If @var{a} is a column vector and @var{x} is a +column vector of length @var{n}, in a Galois Field then + +@code{convmtx (@var{a}, @var{n}) * @var{x}} + +gives the convolution of of @var{a} and @var{x} and is the +same as @code{conv (@var{a}, @var{x})}. The difference is if +many vectors are to be convolved with the same vector, then +this technique is possibly faster + +Similarly, if @var{a} is a row vector and @var{x} is a row +vector of length @var{n}, then + +@code{@var{x} * convmtx (@var{a}, @var{n})} + +is the same as @code{conv (@var{x}, @var{a})} +See also: conv +@end deftypefn + + + +@node cosets, cyclgen, convmtx, Function Reference +@subsection cosets + +@deftypefn {Function File} {} cosets (@var{m}, @var{prim}) + +Finds the elements of GF(2^@var{m}) with primitive polynomial @var{prim}, +that share the same minimum polynomial. Returns a cell array of the +partitioning of GF(2^@var{m}) +@end deftypefn + + + +@node cyclgen, cyclpoly, cosets, Function Reference +@subsection cyclgen + +@deftypefn {Loadable Function} {@var{h} =} cyclgen (@var{n}, @var{p}) +@deftypefnx {Loadable Function} {@var{h} =} cyclgen (@var{n}, @var{p}, @var{typ}) +@deftypefnx {Loadable Function} {[@var{h}, @var{g}] =} cyclgen (@dots{}) +@deftypefnx {Loadable Function} {[@var{h}, @var{g}, @var{k}] =} cyclgen (@dots{}) +Produce the parity check and generator matrix of a cyclic code. The parity +check matrix is returned as a @var{m} by @var{n} matrix, representing the +[@var{n},@var{k}] cyclic code. @var{m} is the order of the generator +polynomial @var{p} and the message length @var{k} is given by +@code{@var{n} - @var{m}}. + +The generator polynomial can either be a vector of ones and zeros, +and length @var{m} representing, +@tex +$$ p_0 + p_1 x + p_2 x^2 + \cdots + p_m x^{m-1} $$ +@end tex +@ifnottex + +@example +@var{p}(1) + @var{p}(2) * x + @var{p}(3) * x^2 + ... + @var{p}(@var{m}) * x^(m-1) +@end example +@end ifnottex + +The terms of the polynomial are stored least-significant term first. +Alternatively, @var{p} can be an integer representation of the same +polynomial. + +The form of the parity check matrix is determined by @var{typ}. If +@var{typ} is 'system', a systematic parity check matrix is produced. If +@var{typ} is 'nosys' and non-systematic parity check matrix is produced. + +If requested @code{cyclgen} also returns the @var{k} by @var{n} generator +matrix @var{g}. +See also: hammgen, gen2par, cyclpoly +@end deftypefn + + + +@node cyclpoly, de2bi, cyclgen, Function Reference +@subsection cyclpoly + +@deftypefn {Loadable Function} {@var{y} =} cyclpoly (@var{n}, @var{k}) +@deftypefnx {Loadable Function} {@var{y} =} cyclpoly (@var{n}, @var{k}, @var{opt}) +@deftypefnx {Loadable Function} {@var{y} =} cyclpoly (@var{n}, @var{k}, @var{opt}, @var{rep}) +This function returns the cyclic generator polynomials of the code +[@var{n},@var{k}]. By default the polynomial with the smallest weight +is returned. However this behavior can be overridden with the @var{opt} +flag. Valid values of @var{opt} are: + +@table @asis +@item @code{"all\"} +Returns all of the polynomials of the code [@var{n},@var{k}] +@item @code{\"min\"} +Returns the polynomial of minimum weight of the code [@var{n},@var{k}] +@item @code{\"max\"} +Returns the polynomial of the maximum weight of the code [@var{n},@var{k}] +@item @var{l} +Returns the polynomials having exactly the weight @var{l} +@end table + +The polynomials are returns as row-vectors in the variable @var{y}. Each +row of @var{y} represents a polynomial with the least-significant term +first. The polynomials can be returned with an integer representation +if @var{rep} is @code{\"integer\"}. The default behavior is given if @var{rep} +is @code{\"polynomial\"}. +See also: gf, isprimitive +@end deftypefn + + + +@node de2bi, decode, cyclpoly, Function Reference +@subsection de2bi + +@deftypefn {Function File} {@var{b} =} de2bi (@var{d}) +@deftypefnx {Function File} {@var{b} =} de2bi (@var{d}, @var{n}) +@deftypefnx {Function File} {@var{b} =} de2bi (@var{d}, @var{n}, @var{p}) +@deftypefnx {Function File} {@var{b} =} de2bi (@var{d}, @dots{}, @var{f}) + +Convert a non-negative integer to bit vector + +The variable @var{d} must be a vector of non-negative integers. @code{de2bi} +then returns a matrix where each row represents the binary representation +of elements of @var{d}. If @var{n} is defined then the returned matrix +will have @var{n} columns. This number of columns can be either larger +than the minimum needed and zeros will be added to the msb of the +binary representation or smaller than the minimum in which case the +least-significant part of the element is returned + +If @var{p} is defined then it is used as the base for the decomposition +of the returned values. That is the elements of the returned value are +between '0' and 'p-1'. (@var{p} must have a value of 2 or higher.) + +The variable @var{f} defines whether the first or last element of @var{b} +is considered to be the most-significant. Valid values of @var{f} are +"right-msb" or "left-msb". By default @var{f} is "right-msb" + +See also: bi2de +@end deftypefn + + + +@node decode, deconv, de2bi, Function Reference +@subsection decode + +@deftypefn {Function File} {@var{msg} =} decode (@var{code}, @var{n}, @var{k}) +@deftypefnx {Function File} {@var{msg} =} decode (@var{code}, @var{n}, @var{k}, @var{typ}) +@deftypefnx {Function File} {@var{msg} =} decode (@var{code}, @var{n}, @var{k}, @var{typ}, @var{opt1}) +@deftypefnx {Function File} {@var{msg} =} decode (@var{code}, @var{n}, @var{k}, @var{typ}, @var{opt1}, @var{opt2}) +@deftypefnx {Function File} {[@var{msg}, @var{err}] =} decode (@dots{}) +@deftypefnx {Function File} {[@var{msg}, @var{err}, @var{ccode}] =} decode (@dots{}) +@deftypefnx {Function File} {[@var{msg}, @var{err}, @var{ccode}, @var{cerr}] =} decode (@dots{}) + +Top level block decoder. This function makes use of the lower level +functions such as @code{cyclpoly}, @code{cyclgen}, @code{hammgen}, and +@code{bchenco}. The coded message to decode is pass in @var{code}, the +codeword length is @var{n} and the message length is @var{k}. This +function is used to decode messages using either: + +@table @asis +@item A [n,k] linear block code defined by a generator matrix +@item A [n,k] cyclic code defined by a generator polynomial +@item A [n,k] Hamming code defined by a primitive polynomial +@item A [n,k] BCH code code defined by a generator polynomial +@end table + +The type of coding to use is defined by the variable @var{typ}. This +variable is a string taking one of the values + +@table @code +@item "linear" +@itemx "linear/binary" +A linear block code is assumed with the message @var{msg} being in a +binary format. In this case the argument @var{opt1} is the generator +matrix, and is required. Additionally, @var{opt2} containing the +syndrome lookup table (see @code{syndtable}) can also be passed +@item "cyclic" +@itemx "cyclic/binary" +A cyclic code is assumed with the message @var{msg} being in a binary +format. The generator polynomial to use can be defined in @var{opt1} +The default generator polynomial to use will be +@code{cyclpoly (@var{n}, @var{k})}. Additionally, @var{opt2} containing the +syndrome lookup table (see @code{syndtable}) can also be passed +@item "hamming" +@itemx "hamming/binary" +A Hamming code is assumed with the message @var{msg} being in a binary +format. In this case @var{n} must be of an integer of the form +@code{2^@var{m}-1}, where @var{m} is an integer. In addition @var{k} +must be @code{@var{n}-@var{m}}. The primitive polynomial to use can +be defined in @var{opt1}. The default primitive polynomial to use is +the same as defined by @code{hammgen}. The variable @var{opt2} should +not be defined +@item "bch" +@itemx "bch/binary" +A BCH code is assumed with the message @var{msg} being in a binary +format. The primitive polynomial to use can be defined in @var{opt2} +The error correction capability of the code can also be defined in +@var{opt1}. Use the empty matrix [] to let the error correction +capability take the default value +@end table + +In addition the argument "binary" above can be replaced with "decimal", +in which case the message is assumed to be a decimal vector, with each +value representing a symbol to be coded. The binary format can be in two +forms + +@table @code +@item An @var{x}-by-@var{n} matrix +Each row of this matrix represents a symbol to be decoded +@item A vector with length divisible by @var{n} +The coded symbols are created from groups of @var{n} elements of this vector +@end table + +The decoded message is return in @var{msg}. The number of errors encountered +is returned in @var{err}. If the coded message format is "decimal" or a +"binary" matrix, then @var{err} is a column vector having a length equal +to the number of decoded symbols. If @var{code} is a "binary" vector, then +@var{err} is the same length as @var{msg} and indicated the number of +errors in each symbol. If the value @var{err} is positive it indicates the +number of errors corrected in the corresponding symbol. A negative value +indicates an uncorrectable error. The corrected code is returned in +@var{ccode} in a similar format to the coded message @var{msg}. The +variable @var{cerr} contains similar data to @var{err} for @var{ccode} + +It should be noted that all internal calculations are performed in the +binary format. Therefore for large values of @var{n}, it is preferable +to use the binary format to pass the messages to avoid possible rounding +errors. Additionally, if repeated calls to @code{decode} will be performed, +it is often faster to create a generator matrix externally with the +functions @code{hammgen} or @code{cyclgen}, rather than let @code{decode} +recalculate this matrix at each iteration. In this case @var{typ} should +be "linear". The exception to this case is BCH codes, where the required +syndrome table is too large. The BCH decoder, decodes directly from the +polynomial never explicitly forming the syndrome table + +See also: encode, cyclgen, cyclpoly, hammgen, bchdeco, bchpoly, syndtable +@end deftypefn + + + +@node deconv, deintrlv, decode, Function Reference +@subsection deconv + +@deftypefn {Function File} {} deconv (@var{y}, @var{a}) +Deconvolve two Galois vectors + +@code{[b, r] = deconv (y, a)} solves for @var{b} and @var{r} such that +@code{y = conv (a, b) + r} + +If @var{y} and @var{a} are polynomial coefficient vectors, @var{b} will +contain the coefficients of the polynomial quotient and @var{r} will be +a remainder polynomial of lowest order +See also: conv +@end deftypefn + + + +@node deintrlv, demodmap, deconv, Function Reference +@subsection deintrlv + +@deftypefn {Function File} {@var{deintrlvd} =} deintrlv (@var{data}, @var{elements}) +Restore elements of @var{data} according to @var{elements} +See also: intrlv +@end deftypefn + + + +@node demodmap, det, deintrlv, Function Reference +@subsection demodmap + +@deftypefn {Function File} {z =} demodmap (@var{y}, @var{fd}, @var{fs}, "ask", @var{m}) +@deftypefnx {Function File} {z =} demodmap (@var{y}, @var{fd}, @var{fs}, "fsk", @var{m}, @var{tone}) +@deftypefnx {Function File} {z =} demodmap (@var{y}, @var{fd}, @var{fs}, "msk") +@deftypefnx {Function File} {z =} demodmap (@var{y}, @var{fd}, @var{fs}, "psk", @var{m}) +@deftypefnx {Function File} {z =} demodmap (@var{y}, @var{fd}, @var{fs}, "qask", @var{m}) +@deftypefnx {Function File} {z =} demodmap (@var{y}, @var{fd}, @var{fs}, "qask/cir", @var{nsig}, @var{amp}, @var{phs}) +@deftypefnx {Function File} {z =} demodmap (@var{y}, @var{fd}, @var{fs}, "qask/arb", @var{inphase}, @var{quadr}) +@deftypefnx {Function File} {z =} demodmap (@var{y}, @var{fd}, @var{fs}, "qask/arb", @var{map}) +@deftypefnx {Function File} {z =} demodmap (@var{y}, [@var{fd}, @var{off}], @dots{}) + +Demapping of an analog signal to a digital signal. The function +@code{demodmap} must have at least three input arguments and one output +argument. Argument @var{y} is a complex variable representing the analog +signal to be demapped. The variables @var{fd} and @var{fs} are the +sampling rate of the of digital signal and the sampling rate of the +analog signal respectively. It is required that @code{@var{fs}/@var{fd}} +is an integer + +The available mapping of the digital signal are + +@table @asis +@item "ask" +Amplitude shift keying +@item "fsk" +Frequency shift keying +@item "msk" +Minimum shift keying +@item "psk" +Phase shift keying +@item "qask" +@itemx "qsk" +@itemx "qam" +Quadrature amplitude shift keying +@end table + +In addition the "qask", "qsk" and "qam" method can be modified with the +flags "/cir" or "/arb". That is "qask/cir" and "qask/arb", etc are valid +methods and give circular- and arbitrary-qask mappings respectively. Also +the method "fsk" and "msk" can be modified with the flag "/max", in which +case @var{y} is assumed to be a matrix with @var{m} columns, representing +the symbol correlations + +The variable @var{m} is the order of the modulation to use. By default +this is 2, and in general should be specified + +For "qask/cir", the additional arguments are the same as for +@code{apkconst}, and you are referred to @code{apkconst} for the definitions +of the additional variables + +For "qask/arb", the additional arguments @var{inphase} and @var{quadr} give +the in-phase and quadrature components of the mapping, in a similar mapping +to the outputs of @code{qaskenco} with one argument. Similar @var{map} +represents the in-phase and quadrature components of the mapping as +the real and imaginary parts of the variable @var{map} +See also: modmap, ddemodce, ademodce, apkconst, qaskenco +@end deftypefn + + + +@node det, dftmtx, demodmap, Function Reference +@subsection det + +@deftypefn {Loadable Function} {@var{d} =} det (@var{a}) +Compute the determinant of the Galois array @var{a} +@end deftypefn + + + +@node dftmtx, diag, det, Function Reference +@subsection dftmtx + +@deftypefn {Function File} {@var{d} =} dftmtx (@var{a}) + +Form a matrix, that can be used to perform Fourier transforms in +a Galois Field + +Given that @var{a} is an element of the Galois Field GF(2^m), and +that the minimum value for @var{k} for which @code{@var{a} ^ @var{k}} +is equal to one is @code{2^m - 1}, then this function produces a +@var{k}-by-@var{k} matrix representing the discrete Fourier transform +over a Galois Field with respect to @var{a}. The Fourier transform of +a column vector is then given by @code{dftmtx (@var{a}) * @var{x}} + +The inverse Fourier transform is given by @code{dftmtx (1 / @var{a})} +@end deftypefn + + + +@node diag, dpcmdeco, dftmtx, Function Reference +@subsection diag + +@deftypefn {Loadable Function} {} diag (@var{v}, @var{k}) +Return a diagonal matrix with Galois vector @var{v} on diagonal @var{k} +The second argument is optional. If it is positive, the vector is placed on +the @var{k}-th super-diagonal. If it is negative, it is placed on the +@var{-k}-th sub-diagonal. The default value of @var{k} is 0, and the +vector is placed on the main diagonal. For example, + +@example +diag (gf ([1, 2, 3], 2), 1) +ans = +GF(2^2) array. Primitive Polynomial = D^2+D+1 (decimal 7) + +Array elements = + + 0 1 0 0 + 0 0 2 0 + 0 0 0 3 + 0 0 0 0 + +@end example +@end deftypefn + + + +@node dpcmdeco, dpcmenco, diag, Function Reference +@subsection dpcmdeco + +@deftypefn {Function File} {@var{sig} =} dpcmdeco (@var{indx}, @var{codebook}, @var{predictor}) +Decode using differential pulse code modulation (DPCM) + +@table @code +@item sig = dpcmdeco (indx, codebook, predictor) +Decode the signal coded by DPCM +Use the prediction model and the coded prediction error given by a codebook and +the index of each sample in this codebook + +@end table +See also: dpcmenco, dpcmopt +@end deftypefn + + + +@node dpcmenco, dpcmopt, dpcmdeco, Function Reference +@subsection dpcmenco + +@deftypefn {Function File} {@var{qidx} =} dpcmenco (@var{sig}, @var{codebook}, @var{partition}, @var{predictor}) +@deftypefnx {Function File} {[@var{qidx}, @var{q}] =} dpcmenco (@var{sig}, @var{codebook}, @var{partition}, @var{predictor}) +@deftypefnx {Function File} {[@var{qidx}, @var{q}, @var{d}] =} dpcmenco (@dots{}) +Encode using differential pulse code modulation (DPCM) + +@table @code +@item qidx = dpcmenco (sig, codebook, partition, predictor) +Determine position of the prediction error in a strictly monotonic table (partition) +The predictor vector describes a m-th order prediction for the +output according to the following equation +y(k) = p(1)sig(k-1) + p(2)sig(k-2) + ... + p(m-1)sig(k-m+1) + p(m)sig(k-m) , +where the predictor vector is given by +predictor = [0, p(1), p(2), p(3),..., p(m-1), p(m)] + +@item [qidx, q] = dpcmenco (sig, codebook, partition, predictor) +Also return the quantized values + +@item [qidx, q, d] = dpcmenco (...) +Also compute distortion: mean squared distance of original sig from the +corresponding quantized values + +@end table +See also: dpcmdeco, dpcmopt, quantiz +@end deftypefn + + + +@node dpcmopt, egolaydec, dpcmenco, Function Reference +@subsection dpcmopt + +@deftypefn {Function File} {@var{predictor} =} dpcmopt (@var{training_set}, @var{ord}) +@deftypefnx {Function File} {[@var{predictor}, @var{partition}, @var{codebook}] =} dpcmopt (@var{training_set}, @var{ord}, @var{cb}) +Optimize the DPCM parameters and codebook + +It uses the Levinson-Durbin algorithm to find the all-pole IIR filter +using the autocorrelation sequence. After the best predictor is found, +it uses the Lloyds algorithm to find the best codebook and partition +for the interval + +@table @code +@item predictor = dpcmopt (training_set, ord) +Optimize the DPCM parameters using the Levinson-Durbin algorithm +The predictor vector describes a m-th order prediction for the +output according to the following equation +y(k) = p(1)sig(k-1) + p(2)sig(k-2) + ... + p(m-1)sig(k-m+1) + p(m)sig(k-m) +where the predictor vector is given by +predictor = [0, p(1), p(2), p(3),..., p(m-1), p(m)] + +training_set is the training data used to find the best predictor + +ord is the order of the desired prediction model + +@item [predictor, partition, codebook] = dpcmopt (training_set,ord,cb) +Optimize the DPCM parameters and also uses the Lloyds algorithm to find +the best codebook and partition for the given training signal + +cb might be the initial codebook used by Lloyds algorithm or +the length of the desired codebook + +@end table +See also: dpcmenco, dpcmdeco, levinson, lloyds +@end deftypefn + + + +@node egolaydec, egolayenc, dpcmopt, Function Reference +@subsection egolaydec + +@deftypefn {Function File} {[@var{C}, @var{err}] =} egolaydec (@var{R}) +Decode Extended Golay code + +Given @var{R}, the received Extended Golay code, this function tries to +decode it using the Extended Golay code parity check matrix +Extended Golay code (24,12) which can correct up to 3 errors + +The received code @var{R}, needs to be of length Nx24, for encoding. We can +decode several codes at once, if they are stacked as a matrix of 24 columns, +each code in a separate row + +The generator used in here is same as obtained from the function +@code{egolaygen} + +The function returns @var{C}, the error-corrected code word from the received +word. If decoding failed, @var{err} value is 1, otherwise it is 0 + +Extended Golay code (24,12) which can correct up to 3 +errors. Decoding algorithm follows from Lin & Costello + +Ref: Lin & Costello, pg 128, Ch4, "Error Control Coding", 2nd ed, Pearson + +@example +@group +msg = rand (10, 12) > 0.5; +c1 = egolayenc (msg); +c1(:,1) = mod (c1(:,1) + 1, 2) +c2 = egolaydec (c1) +@end group +@end example + +See also: egolaygen, egolayenc +@end deftypefn + + + +@node egolayenc, egolaygen, egolaydec, Function Reference +@subsection egolayenc + +@deftypefn {Function File} {@var{C} =} egolayenc (@var{M}) +Encode with Extended Golay code + +The message @var{M}, needs to be of size Nx12, for encoding +We can encode several messages, into codes at once, if they +are stacked in the order suggested + +The generator used in here is same as obtained from the +function @code{egolaygen}. Extended Golay code (24,12) which can correct +up to 3 errors + +@example +@group +msg = rand (10, 12) > 0.5; +c = egolayenc (msg) +@end group +@end example + +See also: egolaygen, egolaydec +@end deftypefn + + + +@node egolaygen, encode, egolayenc, Function Reference +@subsection egolaygen + +@deftypefn {Function File} {[@var{G}, @var{P}] =} egolaygen () +Extended Golay code generator matrix + +Returns @var{G}, the Extended Golay code (24,12) generator matrix, +which can correct up to 3 errors. @var{P} is the parity +check matrix, for this code + +See also: egolaydec, egolayenc +@end deftypefn + + + +@node encode, exp, egolaygen, Function Reference +@subsection encode + +@deftypefn {Function File} {@var{code} =} encode (@var{msg}, @var{n}, @var{k}) +@deftypefnx {Function File} {@var{code} =} encode (@var{msg}, @var{n}, @var{k}, @var{typ}) +@deftypefnx {Function File} {@var{code} =} encode (@var{msg}, @var{n}, @var{k}, @var{typ}, @var{opt}) +@deftypefnx {Function File} {[@var{code}, @var{added}] =} encode (@dots{}) + +Top level block encoder. This function makes use of the lower level +functions such as @code{cyclpoly}, @code{cyclgen}, @code{hammgen}, and +@code{bchenco}. The message to code is pass in @var{msg}, the +codeword length is @var{n} and the message length is @var{k}. This +function is used to encode messages using either: + +@table @asis +@item A [n,k] linear block code defined by a generator matrix +@item A [n,k] cyclic code defined by a generator polynomial +@item A [n,k] Hamming code defined by a primitive polynomial +@item A [n,k] BCH code code defined by a generator polynomial +@end table + +The type of coding to use is defined by the variable @var{typ}. This +variable is a string taking one of the values + +@table @code +@item "linear" +@itemx "linear/binary" +A linear block code is assumed with the coded message @var{code} being in +a binary format. In this case the argument @var{opt} is the generator +matrix, and is required +@item "cyclic" +@itemx "cyclic/binary" +A cyclic code is assumed with the coded message @var{code} being in a +binary format. The generator polynomial to use can be defined in @var{opt} +The default generator polynomial to use will be +@code{cyclpoly (@var{n}, @var{k})} +@item "hamming" +@itemx "hamming/binary" +A Hamming code is assumed with the coded message @var{code} being in a +binary format. In this case @var{n} must be of an integer of the form +@code{2^@var{m}-1}, where @var{m} is an integer. In addition @var{k} +must be @code{@var{n}-@var{m}}. The primitive polynomial to use can +be defined in @var{opt}. The default primitive polynomial to use is +the same as defined by @code{hammgen} +@item "bch" +@itemx "bch/binary" +A BCH code is assumed with the coded message @var{code} being in a binary +format. The generator polynomial to use can be defined in @var{opt} +The default generator polynomial to use will be +@code{bchpoly (@var{n}, @var{k})} +@end table + +In addition the argument "binary" above can be replaced with "decimal", +in which case the message is assumed to be a decimal vector, with each +value representing a symbol to be coded. The binary format can be in two +forms + +@table @code +@item An @var{x}-by-@var{k} matrix +Each row of this matrix represents a symbol to be coded +@item A vector +The symbols are created from groups of @var{k} elements of this vector +If the vector length is not divisible by @var{k}, then zeros are added +and the number of zeros added is returned in @var{added} +@end table + +It should be noted that all internal calculations are performed in the +binary format. Therefore for large values of @var{n}, it is preferable +to use the binary format to pass the messages to avoid possible rounding +errors. Additionally, if repeated calls to @code{encode} will be performed, +it is often faster to create a generator matrix externally with the +functions @code{hammgen} or @code{cyclgen}, rather than let @code{encode} +recalculate this matrix at each iteration. In this case @var{typ} should +be "linear". The exception to this case is BCH codes, whose encoder +is implemented directly from the polynomial and is significantly faster + +See also: decode, cyclgen, cyclpoly, hammgen, bchenco, bchpoly +@end deftypefn + + + +@node exp, eyediagram, encode, Function Reference +@subsection exp + +@deftypefn {Loadable Function} {} exp (@var{x}) +Compute the anti-logarithm for each element of @var{x} for a Galois +array +@end deftypefn + + + +@node eyediagram, fft, exp, Function Reference +@subsection eyediagram + +@deftypefn {Function File} {} eyediagram (@var{x}, @var{n}) +@deftypefnx {Function File} {} eyediagram (@var{x}, @var{n}, @var{per}) +@deftypefnx {Function File} {} eyediagram (@var{x}, @var{n}, @var{per}, @var{off}) +@deftypefnx {Function File} {} eyediagram (@var{x}, @var{n}, @var{per}, @var{off}, @var{str}) +@deftypefnx {Function File} {} eyediagram (@var{x}, @var{n}, @var{per}, @var{off}, @var{str}, @var{h}) +@deftypefnx {Function File} {@var{h} =} eyediagram (@dots{}) + +Plot the eye-diagram of a signal. The signal @var{x} can be either in one +of three forms + +@table @asis +@item A real vector +In this case the signal is assumed to be real and represented by the vector +@var{x}. A single eye-diagram representing this signal is plotted +@item A complex vector +In this case the in-phase and quadrature components of the signal are +plotted separately +@item A matrix with two columns +In this case the first column represents the in-phase and the second the +quadrature components of a complex signal +@end table + +Each line of the eye-diagram has @var{n} elements and the period is assumed +to be given by @var{per}. The time axis is then [-@var{per}/2 @var{per}/2] +By default @var{per} is 1 + +By default the signal is assumed to start at -@var{per}/2. This can be +overridden by the @var{off} variable, which gives the number of samples +to delay the signal + +The string @var{str} is a plot style string (example "r+"), +and by default is the default gnuplot line style + +The figure handle to use can be defined by @var{h}. If @var{h} is not +given, then the next available figure handle is used. The figure handle +used in returned on @var{hout} +See also: scatterplot +@end deftypefn + + + +@node fft, fibodeco, eyediagram, Function Reference +@subsection fft + +@deftypefn {Function File} {} fft (@var{x}) + +If @var{x} is a column vector, finds the FFT over the primitive element +of the Galois Field of @var{x}. If @var{x} is in the Galois Field +GF(2^@var{m}), then @var{x} must have @code{2^@var{m} - 1} elements +@end deftypefn + + + +@node fibodeco, fiboenco, fft, Function Reference +@subsection fibodeco + +@deftypefn {Function File} {} fibodeco (@var{code}) + +Returns the decoded Fibonacci value from the binary vectors @var{code} +Universal codes like Fibonacci codes have a useful synchronization property, +only for 255 maximum value we have designed these routines. We assume +user has partitioned the code into several unique segments based on +the suffix property of unique strings "11" and we just decode the +parts. Partitioning the stream is as simple as identifying the +"11" pairs that occur, at the terminating ends. This system implements +the standard binary Fibonacci codes, which means that row vectors +can only contain 0 or 1. Ref: @url{http://en.wikipedia.org/wiki/Fibonacci_coding} + +@example +@group +fibodeco (@{[0 1 0 0 1 1]@}) + @result{} 10 +fibodeco (@{[1 1], [0 1 1], [0 0 1 1], [1 0 1 1]@}) + @result{} [1, 2, 3, 4] +@end group +@end example +See also: fiboenco +@end deftypefn + + + +@node fiboenco, fibosplitstream, fibodeco, Function Reference +@subsection fiboenco + +@deftypefn {Function File} {} fiboenco (@var{num}) + +Returns the cell-array of encoded Fibonacci value from the column vectors @var{num} +Universal codes like Fibonacci codes have a useful synchronization +property, only for 255 maximum value we have designed these routines. We assume +user has partitioned the code into several unique segments based on +the suffix property of unique elements [1 1] and we just decode the +parts. Partitioning the stream is as simple as identifying the [1 1] +pairs that occur, at the terminating ends. This system implements +the standard binary Fibonacci codes, which means that row vectors +can only contain 0 or 1. Ref: http://en.wikipedia.org/wiki/Fibonacci_coding +Ugly O(k.N^2) encoder.Ref: Wikipedia article accessed March, 2006 +@url{http://en.wikipedia.org/wiki/Fibonacci_coding}, UCI Data Compression +Book, @url{http://www.ics.uci.edu/~dan/pubs/DC-Sec3.html}, (accessed +October 2006) + +@example +@group +fiboenco (10) + @result{} @{[ 0 1 0 0 1 1]@} +fiboenco (1:4) + @result{} @{[1 1], [0 1 1], [0 0 1 1], [1 0 1 1]@} +@end group +@end example +See also: fibodeco +@end deftypefn + + + +@node fibosplitstream, filter, fiboenco, Function Reference +@subsection fibosplitstream + +@deftypefn {Function File} {} fibosplitstream (@var{code}) + +Returns the split data stream at the word boundaries +Assuming the stream was originally encoded using @code{fiboenco} +and this routine splits the stream at the points where "11" +occur together & gives us the code-words which +can later be decoded from the @code{fibodeco} This however doesn't +mean that we intend to verify if all the codewords are correct, +and in fact the last symbol in the return list can or can not be +a valid codeword + +A example use of @code{fibosplitstream} would be +@example +@group +fibodeco (fibosplitstream ([fiboenco(randint (1, 100, [0, 255]))@{:@}])) +fibodeco (fibosplitstream ([fiboenco(1:10)@{:@}])) +@end group +@end example +See also: fiboenco, fibodeco +@end deftypefn + + + +@node filter, finddelay, fibosplitstream, Function Reference +@subsection filter + +@deftypefn {Loadable Function} {y =} filter (@var{b}, @var{a}, @var{x}) +@deftypefnx {Loadable Function} {[@var{y}, @var{sf}] =} filter (@var{b}, @var{a}, @var{x}, @var{si}) + +Digital filtering of vectors in a Galois Field. Returns the solution to +the following linear, time-invariant difference equation over a Galois +Field: +@tex +$$ +\sum_{k=0}^N a_{k+1} y_{n-k} = \sum_{k=0}^M b_{k+1} x_{n-k}, \qquad + 1 \le n \le P +$$ +@end tex +@ifnottex + +@smallexample +@group + N M + SUM a(k+1) y(n-k) = SUM b(k+1) x(n-k) for 1<=n<=length(x) + k=0 k=0 +@end group +@end smallexample +@end ifnottex + +@noindent +where +@tex + $a \in \Re^{N-1}$, $b \in \Re^{M-1}$, and $x \in \Re^P$ +@end tex +@ifnottex + N=length(a)-1 and M=length(b)-1 +@end ifnottex +An equivalent form of this equation is: +@tex +$$ +y_n = -\sum_{k=1}^N c_{k+1} y_{n-k} + \sum_{k=0}^M d_{k+1} x_{n-k}, \qquad + 1 \le n \le P +$$ +@end tex +@ifnottex + +@smallexample +@group + N M + y(n) = - SUM c(k+1) y(n-k) + SUM d(k+1) x(n-k) for 1<=n<=length(x) + k=1 k=0 +@end group +@end smallexample +@end ifnottex + +@noindent +where +@tex +$c = a/a_1$ and $d = b/a_1$ +@end tex +@ifnottex + c = a/a(1) and d = b/a(1) +@end ifnottex + +If the fourth argument @var{si} is provided, it is taken as the +initial state of the system and the final state is returned as +@var{sf}. The state vector is a column vector whose length is +equal to the length of the longest coefficient vector minus one +If @var{si} is not supplied, the initial state vector is set to all +zeros +@end deftypefn + + + +@node finddelay, fmdemod, filter, Function Reference +@subsection finddelay + +@deftypefn {Function File} {@var{d} =} finddelay (@var{x}, @var{y}) +Estimate the delay between times series @var{x} and time series @var{y} by +correlating and finding the peak. The index of the peak correlation +is returned in @var{d} + +Inputs: +@itemize +@var{x}, @var{y}: signals +@end itemize + +Output: +@itemize +@var{d}: The delay between the two signals +@end itemize + +Example: +@example +x = [0, 0, 1, 2, 3]; +y = [1, 2, 3]; +d = finddelay (x, y) +d = -2 +@end example +See also: xcorr +@end deftypefn + + + +@node fmdemod, fmmod, finddelay, Function Reference +@subsection fmdemod + +@deftypefn {Function File} {@var{m} =} fmdemod (@var{s}, @var{fc}, @var{fs}) +Creates the FM demodulation of the signal @var{s} +sampled at frequency @var{fs} with carrier frequency @var{fc} + +Inputs: +@itemize +@item +@var{s}: FM modulated signal + +@item +@var{fc}: carrier frequency + +@item +@var{fs}: sampling frequency +@end itemize + +Output: +@itemize +@var{m}: FM demodulation of the signal +@end itemize + +See also: ammod, amdemod, fmmod +@end deftypefn + + + +@node fmmod, gen2par, fmdemod, Function Reference +@subsection fmmod + +@deftypefn {Function File} {@var{s} =} fmmod (@var{m}, @var{fc}, @var{fs}, @var{freqdev}) +Creates the FM modulation @var{s} of the message signal @var{m} with carrier frequency @var{fc} + +Inputs: +@itemize +@item +@var{m}: sinusoidal message signal + +@item +@var{fc}: carrier frequency + +@item +@var{fs}: sampling frequency + +@item +@var{freqdev}: maximum absolute frequency deviation, assuming @var{m} is in [-1:1] +@end itemize + +Output: +@itemize +@var{s}: The FM modulation of @var{m} +@end itemize + +Demo +@example +demo fmmod +@end example +See also: ammod, fmdemod, amdemod +@end deftypefn + + + +@node gen2par, genqamdemod, fmmod, Function Reference +@subsection gen2par + +@deftypefn {Function File} {@var{par} =} gen2par (@var{gen}) +@deftypefnx {Function File} {@var{gen} =} gen2par (@var{par}) + +Converts binary generator matrix @var{gen} to the parity check matrix +@var{par} and visa-versa. The input matrix must be in standard form +That is a generator matrix must be k-by-n and in the form [eye(k) P] +or [P eye(k)], and the parity matrix must be (n-k)-by-n and of the +form [eye(n-k) P'] or [P' eye(n-k)] + +See also: cyclgen, hammgen +@end deftypefn + + + +@node genqamdemod, genqammod, gen2par, Function Reference +@subsection genqamdemod + +@deftypefn {Loadable Function} {@var{y} =} genqamdemod (@var{x}, @var{C}) +General quadrature amplitude demodulation. The complex envelope +quadrature amplitude modulated signal @var{x} is demodulated using a +constellation mapping specified by the 1D vector @var{C}. +@end deftypefn + + + +@node genqammod, gf, genqamdemod, Function Reference +@subsection genqammod + +@deftypefn {Function File} {@var{y} =} genqammod (@var{x}, @var{c}) + +Modulates an information sequence of integers @var{x} in the range +@code{[0 @dots{} M-1]} onto a quadrature amplitude modulated signal +@var{y}, where @code{M = length (c) - 1} and @var{c} is a 1D vector +specifying the signal constellation mapping to be used. An example of +combined 4PAM-4PSK is + +@example +@group +d = randint (1, 1e4, 8); +c = [1+j -1+j -1-j 1-j 1+sqrt(3) j*(1+sqrt(3)) -1-sqrt(3) -j*(1+sqrt(3))]; +y = genqammod (d, c); +z = awgn (y, 20); +plot (z, "rx") +@end group +@end example +See also: genqamdemod +@end deftypefn + + + +@node gf, gftable, genqammod, Function Reference +@subsection gf + +#endif + "-*- texinfo -*- +\ + + + +@node gftable, gfweight, gf, Function Reference +@subsection gftable + +@deftypefn {Function File} {} gftable (@var{m}, @var{primpoly}) + +This function exists for compatibility with matlab. As the Octave Galois +fields store a copy of the lookup tables for every field in use internally, +there is no need to use this function + +See also: gf +@end deftypefn + + + +@node gfweight, golombdeco, gftable, Function Reference +@subsection gfweight + +@deftypefn {Function File} {@var{w} =} gfweight (@var{gen}) +@deftypefnx {Function File} {@var{w} =} gfweight (@var{gen}, "gen") +@deftypefnx {Function File} {@var{w} =} gfweight (@var{par}, "par") +@deftypefnx {Function File} {@var{w} =} gfweight (@var{p}, n) + +Calculate the minimum weight or distance of a linear block code. The +code can be either defined by its generator or parity check matrix, or +its generator polynomial. By default if the first argument is a matrix, +it is assumed to be the generator matrix of the code. The type of the +matrix can be defined by a flag "gen" for the generator matrix or +"par" for the parity check matrix + +If the first argument is a vector, it is assumed that it defines the +generator polynomial of the code. In this case a second argument is +required that defines the codeword length + +See also: hammgen, cyclpoly, bchpoly +@end deftypefn + + + +@node golombdeco, golombenco, gfweight, Function Reference +@subsection golombdeco + +@deftypefn {Function File} {} golombdeco (@var{code}, @var{m}) + +Returns the Golomb decoded signal vector using @var{code} and @var{m} +Compulsory m is need to be specified. A restrictions is that a +signal set must strictly be non-negative. The value of code +is a cell array of row-vectors which have the encoded Golomb value +for a single sample. The Golomb algorithm is +used to encode the "code" and only that can be meaningfully +decoded. @var{code} is assumed to have been of format generated +by the function @code{golombenco}. Also the parameter @var{m} need to +be a non-zero number, unless which it makes divide-by-zero errors +This function works backward the Golomb algorithm see +@code{golombenco} for more details on that +Reference: Solomon Golomb, Run length Encodings, 1966 IEEE Trans Info Theory + +An example of the use of @code{golombdeco} is +@example +@group +golombdeco (golombenco (1:4, 2), 2) + @result{} [1 2 3 4] +@end group +@end example +See also: golombenco +@end deftypefn + + + +@node golombenco, hammgen, golombdeco, Function Reference +@subsection golombenco + +@deftypefn {Function File} {} golombenco (@var{sig}, @var{m}) + +Returns the Golomb coded signal as cell array +Also total length of output code in bits can be obtained +This function uses a @var{m} need to be supplied for encoding signal vector +into a Golomb coded vector. A restrictions is that +a signal set must strictly be non-negative. Also the parameter @var{m} need to +be a non-zero number, unless which it makes divide-by-zero errors +The Golomb algorithm [1], is used to encode the data into unary coded +quotient part which is represented as a set of 1's separated from +the K-part (binary) using a zero. This scheme doesn't need any +kind of dictionaries, it is a parameterized prefix codes +Implementation is close to O(N^2), but this implementation +*may be* sluggish, though correct. Details of the scheme are, to +encode the remainder(r of number N) using the floor(log2(m)) bits +when rem is in range 0:(2^ceil(log2(m)) - N), and encode it as +r+(2^ceil(log2(m)) - N), using total of 2^ceil(log2(m)) bits +in other instance it doesn't belong to case 1. Quotient is coded +simply just using the unary code. Also according to [2] Golomb codes +are optimal for sequences using the Bernoulli probability model: +P(n)=p^n-1.q & p+q=1, and when M=[1/log2(p)], or P=2^(1/M) + +Reference: 1. Solomon Golomb, Run length Encodings, 1966 IEEE Trans +Info' Theory. 2. Khalid Sayood, Data Compression, 3rd Edition + +An example of the use of @code{golombenco} is +@example +@group +golombenco (1:4, 2) + @result{} @{[0 1], [1 0 0], [1 0 1], [1 1 0 0]@} +golombenco (1:10, 2) + @result{} @{[0 1], [1 0 0], [1 0 1], [1 1 0 0], + [1 1 0 1], [1 1 1 0 0], [1 1 1 0 1], [1 1 1 1 0 0], + [1 1 1 1 0 1], [1 1 1 1 1 0 0]@} +@end group +@end example +See also: golombdeco +@end deftypefn + + + +@node hammgen, helscanintrlv, golombenco, Function Reference +@subsection hammgen + +@deftypefn {Function File} {@var{h} =} hammgen (@var{m}) +@deftypefnx {Function File} {@var{h} =} hammgen (@var{m}, @var{p}) +@deftypefnx {Function File} {[@var{h}, @var{g}] =} hammgen (@dots{}) +@deftypefnx {Function File} {[@var{h}, @var{g}, @var{n}, @var{k}] =} hammgen (@dots{}) + +Produce the parity check and generator matrices of a Hamming code. The +variable @var{m} defines the [@var{n},@var{k}] Hamming code where +@code{@var{n} = 2 ^ @var{m} - 1} and @code{@var{k} = @var{n} - @var{m}} +@var{m} must be between 3 and 16 + +The parity check matrix is generated relative to the primitive polynomial +of GF(2^@var{m}). If @var{p} is specified the default primitive polynomial +of GF(2^@var{m}) is overridden. @var{p} must be a valid primitive +polynomial of the correct order for GF(2^@var{m}) + +The parity check matrix is returned in the @var{m} by @var{n} matrix +@var{h}, and if requested the generator matrix is returned in the @var{k} +by @var{n} matrix @var{g} + +See also: gen2par +@end deftypefn + + + +@node helscanintrlv, huffmandeco, hammgen, Function Reference +@subsection helscanintrlv + +@deftypefn {Function File} {@var{outdata} =} helscanintrlv (@var{data}, @var{nrows}, @var{ncols}, @var{Nshift}) +@var{nrows}-by-@var{ncols} +See also: helscandeintrlv +@end deftypefn + + + +@node huffmandeco, huffmandict, helscanintrlv, Function Reference +@subsection huffmandeco + +@deftypefn {Function File} {@var{sig} =} huffmandeco (@var{hcode}, @var{dict}) +Decode signal encoded by @code{huffmanenco} + +This function uses a dict built from the +@code{huffmandict} and uses it to decode a signal list into a Huffman +list. A restriction is that @var{hcode} is expected to be a binary code + +The returned @var{sig} set that strictly belongs in the range @code{[1,N]} +with @code{N = length (@var{dict})}. Also @var{dict} can only be from the +@code{huffmandict} routine. Whenever decoding fails, those signal values a +re indicated by @code{-1}, and we successively try to restart decoding +from the next bit that hasn't failed in decoding, ad-infinitum. An example +of the use of @code{huffmandeco} is: + +@example +@group +hd = huffmandict (1:4, [0.5 0.25 0.15 0.10]); +hcode = huffmanenco (1:4, hd); +back = huffmandeco (hcode, hd) + @result{} [1 2 3 4] +@end group +@end example +See also: huffmandict, huffmanenco +@end deftypefn + + + +@node huffmandict, huffmanenco, huffmandeco, Function Reference +@subsection huffmandict + +@deftypefn {Function File} {} huffmandict (@var{symb}, @var{prob}) +@deftypefnx {Function File} {} huffmandict (@var{symb}, @var{prob}, @var{toggle}) +@deftypefnx {Function File} {} huffmandict (@var{symb}, @var{prob}, @var{toggle}, @var{minvar}) + +Builds a Huffman code, given a probability list. The Huffman codes +per symbol are output as a list of strings-per-source symbol. A zero +probability symbol is NOT assigned any codeword as this symbol doesn't +occur in practice anyway + +@var{toggle} is an optional argument with values 1 or 0, that starts +building a code based on 1s or 0s, defaulting to 0. Also @var{minvar} +is a boolean value that is useful in choosing if you want to optimize +buffer for transmission in the applications of Huffman coding, however +it doesn't affect the type or average codeword length of the generated +code. An example of the use of @code{huffmandict} is + +@example +@group +huffmandict (symbols, [0.5 0.25 0.15 0.1], 1) + @result{} @{[0], [1 0], [1 1 1], [1 1 0]@} +huffmandict (symbols, 0.25 * ones (1,4), 1) + @result{} @{[1 1], [1 0], [0 1], [0 0]@} + +prob = [0.5 0 0.25 0.15 0.1]; +dict = huffmandict (1:5, prob, 1); +entropy (prob) + @result{} 2.3219 +laverage (dict, prob) + @result{} 1.8500 + +x = [0.2 0.4 0.2 0.1 0.1]; +huffmandict (1, x, 0, true) + @result{} @{[1 0], [0 0], [1 1], [0 1 0], [0 1 1]@} +huffmandict (1, x) + @result{} @{[0 1], [1], [0 0 1], [0 0 0 0], [0 0 0 1]@} +@end group +@end example + +Reference: Dr.Rao's course EE5351 Digital Video Coding, at UT-Arlington +See also: huffmandeco, huffmanenco +@end deftypefn + + + +@node huffmanenco, ifft, huffmandict, Function Reference +@subsection huffmanenco + +@deftypefn {Function File} {} huffmanenco (@var{sig}, @var{dict}) + +Returns the Huffman encoded signal using @var{dict}. This function uses +a @var{dict} built from the @code{huffmandict} and uses it to encode a +signal list into a Huffman list. A restrictions is that a signal set must +strictly belong in the range @code{[1,N]} with @code{N = length (dict)} +Also @var{dict} can only be from the @code{huffmandict} routine +An example of the use of @code{huffmanenco} is + +@example +@group +hd = huffmandict (1:4, [0.5 0.25 0.15 0.10]); +huffmanenco (1:4, hd) + @result{} [1 0 1 0 0 0 0 0 1] +@end group +@end example +See also: huffmandict, huffmandeco +@end deftypefn + + + +@node ifft, intrlv, huffmanenco, Function Reference +@subsection ifft + +@deftypefn {Function File} {} ifft (@var{x}) + +If @var{x} is a column vector, finds the IFFT over the primitive element +of the Galois Field of @var{x}. If @var{x} is in the Galois Field +GF(2^@var{m}), then @var{x} must have @code{2^@var{m} - 1} elements +See also: ifft +@end deftypefn + + + +@node intrlv, inv, ifft, Function Reference +@subsection intrlv + +@deftypefn {Function File} {@var{intrlvd} =} intrlv (@var{data}, @var{elements}) +Interleaved elements of @var{data} according to @var{elements} +See also: deintrlv +@end deftypefn + + + +@node inv, inverse, intrlv, Function Reference +@subsection inv + +@deftypefn {Loadable Function} {[@var{x}, @var{rcond}] =} inv (@var{a}) +Compute the inverse of the square matrix @var{a}. Return an estimate +of the reciprocal condition number if requested, otherwise warn of an +ill-conditioned matrix if the reciprocal condition number is small +@end deftypefn + + + +@node inverse, isequal, inv, Function Reference +@subsection inverse + +@deftypefn {Loadable Function} {[@var{x}, @var{rcond}] =} inverse (@var{a}) +See inv +@end deftypefn + + + +@node isequal, isgalois, inverse, Function Reference +@subsection isequal + +@deftypefn {Function File} {} isequal (@var{x1}, @var{x2}, @dots{}) +Return true if all of @var{x1}, @var{x2}, @dots{} are equal +See also: isequalwithequalnans +@end deftypefn + + + +@node isgalois, isprimitive, isequal, Function Reference +@subsection isgalois + +@deftypefn {Loadable Function} {} isgalois (@var{expr}) +Return 1 if the value of the expression @var{expr} is a Galois Field. +@end deftypefn + + + +@node isprimitive, istrellis, isgalois, Function Reference +@subsection isprimitive + +@deftypefn {Loadable Function} {@var{y} =} isprimitive (@var{a}) +Returns 1 is the polynomial represented by @var{a} is a primitive +polynomial of GF(2). Otherwise it returns zero. + +See also: gf, primpoly +@end deftypefn + + + +@node istrellis, lloyds, isprimitive, Function Reference +@subsection istrellis + +@deftypefn {Function File} {} istrellis (@var{t}) +@deftypefnx {Function File} {[@var{status}, @var{text}] =} istrellis (@var{t}) + +Return true if @var{t} is a valid trellis structure + +If called with two output arguments, @var{text} contains a string indicating +a reason if @var{status} is false or an empty string if @var{status} is true + +See also: poly2trellis, struct +@end deftypefn + + + +@node lloyds, log, istrellis, Function Reference +@subsection lloyds + +@deftypefn {Function File} {[@var{table}, @var{codes}] =} lloyds (@var{sig}, @var{init_codes}) +@deftypefnx {Function File} {[@var{table}, @var{codes}] =} lloyds (@var{sig}, @var{len}) +@deftypefnx {Function File} {[@var{table}, @var{codes}] =} lloyds (@var{sig}, @dots{}, @var{tol}) +@deftypefnx {Function File} {[@var{table}, @var{codes}] =} lloyds (@var{sig}, @dots{}, @var{tol}, @var{type}) +@deftypefnx {Function File} {[@var{table}, @var{codes}, @var{dist}] =} lloyds (@dots{}) +@deftypefnx {Function File} {[@var{table}, @var{codes}, @var{dist}, @var{reldist}] =} lloyds (@dots{}) + +Optimize the quantization table and codes to reduce distortion. This is +based on the article by Lloyd + + S. Lloyd @emph{Least squared quantization in PCM}, IEEE Trans Inform + Theory, Mar 1982, no 2, p129-137 + +which describes an iterative technique to reduce the quantization error +by making the intervals of the table such that each interval has the same +area under the PDF of the training signal @var{sig}. The initial codes to +try can either be given in the vector @var{init_codes} or as scalar +@var{len}. In the case of a scalar the initial codes will be an equi-spaced +vector of length @var{len} between the minimum and maximum value of the +training signal + +The stopping criteria of the iterative algorithm is given by + +@example +abs(@var{dist}(n) - @var{dist}(n-1)) < max(@var{tol}, abs(@var{eps}*max(@var{sig})) +@end example + +By default @var{tol} is 1.e-7. The final input argument determines how the +updated table is created. By default the centroid of the values of the +training signal that fall within the interval described by @var{codes} +are used to update @var{table}. If @var{type} is any other string than +"centroid", this behavior is overridden and @var{table} is updated as +follows + +@example +@var{table} = (@var{code}(2:length(@var{code})) + @var{code}(1:length(@var{code}-1))) / 2 +@end example + +The optimized values are returned as @var{table} and @var{code}. In +addition the distortion of the optimized codes representing the training +signal is returned as @var{dist}. The relative distortion in the final +iteration is also returned as @var{reldist} + +See also: quantiz +@end deftypefn + + + +@node log, lu, lloyds, Function Reference +@subsection log + +@deftypefn {Loadable Function} {} log (@var{x}) +Compute the natural logarithm for each element of @var{x} for a Galois +array +@end deftypefn + + + +@node lu, lz77deco, log, Function Reference +@subsection lu + +@deftypefn {Loadable Function} {[@var{l}, @var{u}, @var{p}] =} lu (@var{a}) +@cindex LU decomposition of Galois matrix +Compute the LU decomposition of @var{a} in a Galois Field. The result is +returned in a permuted form, according to the optional return value +@var{p}. For example, given the matrix +@code{a = gf ([1, 2; 3, 4], 3)}, + +@example +[l, u, p] = lu (a) +@end example + +@noindent +returns + +@example +l = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 1 0 + 6 1 + +u = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 3 4 + 0 7 + +p = + +Permutation Matrix + + 0 1 + 1 0 + +@end example + +Such that @code{@var{p} * @var{a} = @var{l} * @var{u}}. If the argument +@var{p} is not included then the permutations are applied to @var{l} +so that @code{@var{a} = @var{l} * @var{u}}. @var{l} is then a pseudo- +lower triangular matrix. The matrix @var{a} can be rectangular +@end deftypefn + + + +@node lz77deco, lz77enco, lu, Function Reference +@subsection lz77deco + +@deftypefn {Function File} {@var{m} =} lz77deco (@var{c}, @var{alph}, @var{la}, @var{n}) +Lempel-Ziv 77 source algorithm decoding implementation. Where + +@table @asis +@item @var{m} +message decoded (1xN) +@item @var{c} +encoded message (Mx3) +@item @var{alph} +size of alphabet +@item @var{la} +lookahead buffer size +@item @var{n} +sliding window buffer size +@end table +See also: lz77enco +@end deftypefn + + + +@node lz77enco, matdeintrlv, lz77deco, Function Reference +@subsection lz77enco + +@deftypefn {Function File} {@var{c} =} lz77enco (@var{m}, @var{alph}, @var{la}, @var{n}) +Lempel-Ziv 77 source algorithm implementation. Where + +@table @asis +@item @var{c} +encoded message (Mx3) +@item @var{alph} +size of alphabet +@item @var{la} +lookahead buffer size +@item @var{n} +sliding window buffer size +@end table +See also: lz77deco +@end deftypefn + + + +@node matdeintrlv, matintrlv, lz77enco, Function Reference +@subsection matdeintrlv + +@deftypefn {Function File} {@var{intrlvd} =} matdeintrlv (@var{data}, @var{nrows}, @var{ncols}) +Restore elements of @var{data} with a temporary matrix of size +@var{nrows}-by-@var{ncols} +See also: matintrlv +@end deftypefn + + + +@node matintrlv, minpol, matdeintrlv, Function Reference +@subsection matintrlv + +@deftypefn {Function File} {@var{intrlvd} =} matintrlv (@var{data}, @var{nrows}, @var{ncols}) +Interleaved elements of @var{data} with a temporary matrix of size +@var{nrows}-by-@var{ncols} +See also: matdeintrlv +@end deftypefn + + + +@node minpol, modmap, matintrlv, Function Reference +@subsection minpol + +@deftypefn {Function File} {} minpol (@var{v}) + +Finds the minimum polynomial for elements of a Galois Field. For a +vector @var{v} with @math{N} components, representing @math{N} values +in a Galois Field GF(2^@var{m}), return the minimum polynomial in GF(2) +representing those values +@end deftypefn + + + +@node modmap, oct2dec, minpol, Function Reference +@subsection modmap + +@deftypefn {Function File} {} modmap (@var{method}, @dots{}) +@deftypefnx {Function File} {y =} modmap (@var{x}, @var{fd}, @var{fs}, "ask", @var{m}) +@deftypefnx {Function File} {y =} modmap (@var{x}, @var{fd}, @var{fs}, "fsk", @var{m}, @var{tone}) +@deftypefnx {Function File} {y =} modmap (@var{x}, @var{fd}, @var{fs}, "msk") +@deftypefnx {Function File} {y =} modmap (@var{x}, @var{fd}, @var{fs}, "psk", @var{m}) +@deftypefnx {Function File} {y =} modmap (@var{x}, @var{fd}, @var{fs}, "qask", @var{m}) +@deftypefnx {Function File} {y =} modmap (@var{x}, @var{fd}, @var{fs}, "qask/cir", @var{nsig}, @var{amp}, @var{phs}) +@deftypefnx {Function File} {y =} modmap (@var{x}, @var{fd}, @var{fs}, "qask/arb", @var{inphase}, @var{quadr}) +@deftypefnx {Function File} {y =} modmap (@var{x}, @var{fd}, @var{fs}, "qask/arb", @var{map}) + +Mapping of a digital signal to an analog signal. With no output arguments +@code{modmap} plots the constellation of the mapping. In this case the +first argument must be the string @var{method} defining one of "ask", +"fsk", "msk", "qask", "qask/cir" or "qask/arb". The arguments following +the string @var{method} are generally the same as those after the +corresponding string in the function call without output arguments +The exception is @code{modmap ("msk", @var{Fd})} + +With an output argument, @var{y} is the complex mapped analog signal. In +this case the arguments @var{x}, @var{fd} and @var{fs} are required. The +variable @var{x} is the digital signal to be mapped, @var{fd} is the +sampling rate of the of digital signal and the @var{fs} is the sampling +rate of the analog signal. It is required that @code{@var{fs}/@var{fd}} +is an integer + +The available mapping of the digital signal are + +@table @asis +@item "ask" +Amplitude shift keying +@item "fsk" +Frequency shift keying +@item "msk" +Minimum shift keying +@item "psk" +Phase shift keying +@item "qask" +@itemx "qsk" +@itemx "qam" +Quadrature amplitude shift keying +@end table + +In addition the "qask", "qsk" and "qam" method can be modified with the +flags "/cir" or "/arb". That is "qask/cir" and "qask/arb", etc are valid +methods and give circular- and arbitrary-qask mappings respectively + +The additional argument @var{m} is the order of the modulation to use +@var{m} must be larger than the largest element of @var{x}. The variable +@var{tone} is the FSK tone to use in the modulation + +For "qask/cir", the additional arguments are the same as for +@code{apkconst}, and you are referred to @code{apkconst} for the definitions +of the additional variables + +For "qask/arb", the additional arguments @var{inphase} and @var{quadr} give +the in-phase and quadrature components of the mapping, in a similar mapping +to the outputs of @code{qaskenco} with one argument. Similar @var{map} +represents the in-phase and quadrature components of the mapping as +the real and imaginary parts of the variable @var{map} +See also: demodmap, dmodce, amodce, apkconst, qaskenco +@end deftypefn + + + +@node oct2dec, pamdemod, modmap, Function Reference +@subsection oct2dec + +@deftypefn {Function File} {@var{d} =} oct2dec (@var{c}) + +Convert octal to decimal values + +Each element of the octal matrix @var{c} is converted to a decimal value + +See also: base2dec, bin2dec, dec2bin +@end deftypefn + + + +@node pamdemod, pammod, oct2dec, Function Reference +@subsection pamdemod + +@deftypefn {Function File} {@var{y} =} pamdemod (@var{x}, @var{m}) +@deftypefnx {Function File} {@var{y} =} pamdemod (@var{x}, @var{m}, @var{phi}) +@deftypefnx {Function File} {@var{y} =} pamdemod (@var{x}, @var{m}, @var{phi}, @var{type}) + +Demodulates a pulse amplitude modulated signal @var{x} into an +information sequence of integers in the range @code{[0 @dots{} M-1]} +@var{phi} controls the initial phase and @var{type} controls the +constellation mapping. If @var{type} is set to "Bin" will result in +binary encoding, in contrast, if set to "Gray" will give Gray encoding +An example of Gray-encoded 8-PAM is + +@example +@group +d = randint (1, 1e4, 8); +y = pammod (d, 8, 0, "gray"); +z = awgn (y, 20); +d_est = pamdemod (z, 8, 0, "gray"); +plot (z, "rx") +biterr (d, d_est) +@end group +@end example +See also: pammod +@end deftypefn + + + +@node pammod, poly2trellis, pamdemod, Function Reference +@subsection pammod + +@deftypefn {Function File} {@var{y} =} pammod (@var{x}, @var{m}) +@deftypefnx {Function File} {@var{y} =} pammod (@var{x}, @var{m}, @var{phi}) +@deftypefnx {Function File} {@var{y} =} pammod (@var{x}, @var{m}, @var{phi}, @var{type}) + +Modulates an information sequence of integers @var{x} in the range +@code{[0 @dots{} M-1]} onto a pulse amplitude modulated signal @var{y} +@var{phi} controls the initial phase and @var{type} controls the +constellation mapping. If @var{type} is set to "Bin" will result in +binary encoding, in contrast, if set to "Gray" will give Gray encoding +An example of Gray-encoded 8-PAM is + +@example +@group +d = randint (1, 1e4, 8); +y = pammod (d, 8, 0, "gray"); +z = awgn (y, 20); +plot (z, "rx") +@end group +@end example +See also: pamdemod +@end deftypefn + + + +@node poly2trellis, primpoly, pammod, Function Reference +@subsection poly2trellis + +@deftypefn {Function File} {@var{t} =} poly2trellis (@var{m}, @var{g}) + +Convert convolutional code generator polynomials into trellis form + +The arguments @var{m} and @var{g} together describe a rate k/n feedforward +convolutional encoder. The optional argument @var{f} adds feedback support +The output @var{t} is a trellis structure describing +the same encoder with the fields listed below + +The vector @var{m} is a k-by-1 array containing the lengths of each of the +shift registers for the k input bits to the encoder + +The matrix @var{g} is a k-by-n octal-value matrix describing the generation +of each of the n outputs from each of the k inputs. For a particular entry +of @var{g}, the least-significant bit corresponds to the most-delayed input +bit in the kth shift-register + +The optional vector @var{f} is a 1-by-k vector of octal numbers describing +the feedback of each of the shift registers + +The returned trellis structure contains the following fields: + +@table @samp +@item numInputSymbols +The number of k-bit input symbols possible, i.e. 2^k + +@item numOutputSymbols +The number of n-bit output symbols possible, i.e. 2^n + +@item numStates +The number of states in the trellis + +@item nextStates +The state transition table for the trellis. The ith row contains the indices +of the states reachable from the (i-1)th state for each possible input +symbol + +@item outputs +A table of octal-encoded output values for the trellis. The ith row contains +values representing the output symbols produced in the (i-1)th state for each +possible input symbol +@end table + +Input symbols, output symbols, and encoder states are all interpreted with +the lowest indices being the most significant bits + +References: + + [1] S. Lin and D. J. Costello, "Convolutional codes," in @cite{Error + Control Coding}, 2nd ed. Upper Saddle River, NJ: Pearson, 2004, + ch. 11, pp. 453-513 + +See also: istrellis +@end deftypefn + + + +@node primpoly, prod, poly2trellis, Function Reference +@subsection primpoly + +@deftypefn {Loadable Function} {@var{y} =} primpoly (@var{m}) +@deftypefnx {Loadable Function} {@var{y} =} primpoly (@var{m}, @var{opt}) +@deftypefnx {Loadable Function} {@var{y} =} primpoly (@dots{}, "nodisplay\") +Finds the primitive polynomials in GF(2^@var{m}). + +The first form of this function returns the default primitive polynomial of +GF(2^@var{m}). This is the minimum primitive polynomial of the field. The +polynomial representation is printed and an integer representation of the +polynomial is returned + +The call @code{primpoly (@var{m}, @var{opt})} returns one or more primitive +polynomials. The output of the function is dependent of the value of @var{opt}. +Valid values of @var{opt} are: + +@table @asis +@item @code{\"all\"} +Returns all of the primitive polynomials of GF(2^@var{m}) +@item @code{\"min\"} +Returns the minimum primitive polynomial of GF(2^@var{m}) +@item @code{\"max\"} +Returns the maximum primitive polynomial of GF(2^@var{m}) +@item @var{k} +Returns the primitive polynomials having exactly @var{k} non-zero terms +@end table + +The call @code{primpoly (@dots{}, \"nodisplay\")} disables the output of +the polynomial forms of the primitives. The return value is not affected. + +See also: gf, isprimitive +@end deftypefn + + + +@node prod, pskdemod, primpoly, Function Reference +@subsection prod + +@deftypefn {Loadable Function} {} prod (@var{x}, @var{dim}) +Product of elements along dimension @var{dim} of Galois array. If +@var{dim} is omitted, it defaults to 1 (column-wise products) +@end deftypefn + + + +@node pskdemod, pskmod, prod, Function Reference +@subsection pskdemod + +@deftypefn {Function File} {@var{y} =} pamdemod (@var{x}, @var{m}) +@deftypefnx {Function File} {@var{y} =} pamdemod (@var{x}, @var{m}, @var{phi}) +@deftypefnx {Function File} {@var{y} =} pamdemod (@var{x}, @var{m}, @var{phi}, @var{type}) + +Demodulates a complex-baseband phase shift keying modulated signal +into an information sequence of integers in the range +@code{[0 @dots{} M-1]}. @var{phi} controls the initial phase and +@var{type} controls the constellation mapping. If @var{type} is set +to "Bin" will result in binary encoding, in contrast, if set to +"Gray" will give Gray encoding. An example of Gray-encoded 8-PSK is + +@example +@group +d = randint (1, 1e3, 8); +y = pskmod (d, 8, 0, "gray"); +z = awgn (y, 20); +d_est = pskdemod (z, 8, 0, "gray"); +plot (z, "rx") +biterr (d, d_est) +@end group +@end example +See also: pskmod +@end deftypefn + + + +@node pskmod, qamdemod, pskdemod, Function Reference +@subsection pskmod + +@deftypefn {Function File} {@var{y} =} pskmod (@var{x}, @var{m}) +@deftypefnx {Function File} {@var{y} =} pskmod (@var{x}, @var{m}, @var{phi}) +@deftypefnx {Function File} {@var{y} =} pskmod (@var{x}, @var{m}, @var{phi}, @var{type}) + +Modulates an information sequence of integers @var{x} in the range +@code{[0 @dots{} M-1]} onto a complex baseband phase shift keying +modulated signal @var{y}. @var{phi} controls the initial phase and +@var{type} controls the constellation mapping. If @var{type} is set +to "Bin" will result in binary encoding, in contrast, if set to "Gray" +will give Gray encoding. An example of Gray-encoded QPSK is + +@example +@group +d = randint (1, 5e3, 4); +y = pskmod (d, 4, 0, "gray"); +z = awgn (y, 30); +plot (z, "rx") +@end group +@end example +See also: pskdemod +@end deftypefn + + + +@node qamdemod, qammod, pskmod, Function Reference +@subsection qamdemod + +@deftypefn {Function File} {} qamdemod (@var{x}, @var{m}) +Create the QAM demodulation of x with a size of alphabet m +See also: qammod, pskmod, pskdemod +@end deftypefn + + + +@node qammod, qaskdeco, qamdemod, Function Reference +@subsection qammod + +@deftypefn {Function File} {} qammod (@var{x}, @var{m}) +Create the QAM modulation of x with a size of alphabet m +See also: qamdemod, pskmod, pskdemod +@end deftypefn + + + +@node qaskdeco, qaskenco, qammod, Function Reference +@subsection qaskdeco + +@deftypefn {Function File} {@var{msg} =} qaskdeco (@var{c}, @var{m}) +@deftypefnx {Function File} {@var{msg} =} qaskdeco (@var{inphase}, @var{quadr}, @var{m}) +@deftypefnx {Function File} {@var{msg} =} qaskdeco (@dots{}, @var{mnmx}) + +Demaps an analog signal using a square QASK constellation. The input signal +maybe either a complex variable @var{c}, or as two real variables +@var{inphase} and @var{quadr} representing the in-phase and quadrature +components of the signal + +The argument @var{m} must be a positive integer power of 2. By default the +same constellation as created in @code{qaskenco} is used by @code{qaskdeco} +If is possible to change the values of the minimum and maximum of the +in-phase and quadrature components of the constellation to account for +linear changes in the signal values in the received signal. The variable +@var{mnmx} is a 2-by-2 matrix of the following form + +@multitable @columnfractions 0.125 0.05 0.25 0.05 0.25 0.05 +@item @tab | @tab min in-phase @tab , @tab max in-phase @tab | +@item @tab | @tab min quadrature @tab , @tab max quadrature @tab | +@end multitable + +If @code{sqrt (@var{m})} is an integer, then @code{qaskenco} uses a Gray +mapping. Otherwise, an attempt is made to create a nearly square mapping +with a minimum Hamming distance between adjacent constellation points +See also: qaskenco +@end deftypefn + + + +@node qaskenco, qfunc, qaskdeco, Function Reference +@subsection qaskenco + +@deftypefn {Function File} {} qaskenco (@var{m}) +@deftypefnx {Function File} {} qaskenco (@var{msg}, @var{m}) +@deftypefnx {Function File} {@var{y} =} qaskenco (@dots{}) +@deftypefnx {Function File} {[@var{inphase}, @var{quadr}] =} qaskenco (@dots{}) + +Map a digital signal using a square QASK constellation. The argument +@var{m} must be a positive integer power of 2. With two input arguments +the variable @var{msg} represents the message to be encoded. The values +of @var{msg} must be between 0 and @code{@var{m}-1}. In all cases +@code{qaskenco (@var{M})} is equivalent to @code{qaskenco (1:@var{m}, @var{m})} + +Three types of outputs can be created depending on the number of output +arguments. That is + +@table @asis +@item No output arguments +In this case @code{qaskenco} plots the constellation. Only the +points in @var{msg} are plotted, which in the case of a single input +argument is all constellation points +@item A single output argument +The returned variable is a complex variable representing the in-phase +and quadrature components of the mapped message @var{msg}. With, a +single input argument this effectively gives the mapping from symbols +to constellation points +@item Two output arguments +This is the same as one output argument, expect that the in-phase +and quadrature components are returned explicitly. That is + +@example +c = qaskenco (msg, m); +[a, b] = qaskenco (msg, m); +all (c == a + 1i*b) + @result{} 1 +@end example +@end table + +If @code{sqrt (@var{m})} is an integer, then @code{qaskenco} uses a Gray +mapping. Otherwise, an attempt is made to create a nearly square mapping +with a minimum Hamming distance between adjacent constellation points +See also: qaskdeco +@end deftypefn + + + +@node qfunc, qfuncinv, qaskenco, Function Reference +@subsection qfunc + +@deftypefn {Function File} {@var{y} =} qfunc (@var{x}) +Compute the Q function +See also: erfc, erf +@end deftypefn + + + +@node qfuncinv, quantiz, qfunc, Function Reference +@subsection qfuncinv + +@deftypefn {Function File} {@var{y} =} qfuncinv (@var{x}) +Compute the inverse Q function +See also: erfc, erf +@end deftypefn + + + +@node quantiz, randdeintrlv, qfuncinv, Function Reference +@subsection quantiz + +@deftypefn {Function File} {@var{qidx} =} quantiz (@var{x}, @var{table}) +@deftypefnx {Function File} {[@var{qidx}, @var{q}] =} quantiz (@var{x}, @var{table}, @var{codes}) +@deftypefnx {Function File} {[ @var{qidx}, @var{q}, @var{d}] =} quantiz (@dots{}) + +Quantization of an arbitrary signal relative to a partitioning + +@table @code +@item qidx = quantiz (x, table) + Determine position of x in strictly monotonic table. The first + interval, using index 0, corresponds to x <= table(1) + Subsequent intervals are table(i-1) < x <= table(i) + +@item [qidx, q] = quantiz (x, table, codes) + Associate each interval of the table with a code. Use codes(1) + for x <= table(1) and codes(n+1) for table(n) < x <= table(n+1) + +@item [qidx, q, d] = quantiz (...) + Compute distortion as mean squared distance of x from the + corresponding quantization values +@end table +@end deftypefn + + + +@node randdeintrlv, randerr, quantiz, Function Reference +@subsection randdeintrlv + +@deftypefn {Function File} {@var{intrlvd} =} randdeintrlv (@var{data}, @var{state}) +Restore elements of @var{data} with a random permutation +See also: randintrlv, intrlv, deintrlv +@end deftypefn + + + +@node randerr, randint, randdeintrlv, Function Reference +@subsection randerr + +@deftypefn {Function File} {@var{b} =} randerr (@var{n}) +@deftypefnx {Function File} {@var{b} =} randerr (@var{n}, @var{m}) +@deftypefnx {Function File} {@var{b} =} randerr (@var{n}, @var{m}, @var{err}) +@deftypefnx {Function File} {@var{b} =} randerr (@var{n}, @var{m}, @var{err}, @var{seed}) + +Generate a matrix of random bit errors. The size of the matrix is +@var{n} rows by @var{m} columns. By default @var{m} is equal to @var{n} +Bit errors in the matrix are indicated by a 1 + +The variable @var{err} determines the number of errors per row. By +default the return matrix @var{b} has exactly one bit error per row +If @var{err} is a scalar, there each row of @var{b} has exactly this +number of errors per row. If @var{err} is a vector then each row has +a number of errors that is in this vector. Each number of errors has +an equal probability. If @var{err} is a matrix with two rows, then +the first row determines the number of errors and the second their +probabilities + +The variable @var{seed} allows the random number generator to be seeded +with a fixed value. The initial seed will be restored when returning +@end deftypefn + + + +@node randint, randintrlv, randerr, Function Reference +@subsection randint + +@deftypefn {Function File} {@var{b} =} randint (@var{n}) +@deftypefnx {Function File} {@var{b} =} randint (@var{n}, @var{m}) +@deftypefnx {Function File} {@var{b} =} randint (@var{n}, @var{m}, @var{range}) +@deftypefnx {Function File} {@var{b} =} randint (@var{n}, @var{m}, @var{range}, @var{seed}) + +Generate a matrix of random binary numbers. The size of the matrix is +@var{n} rows by @var{m} columns. By default @var{m} is equal to @var{n} + +The range in which the integers are generated will is determined by +the variable @var{range}. If @var{range} is an integer, the value will +lie in the range [0,@var{range}-1], or [@var{range}+1,0] if @var{range} +is negative. If @var{range} contains two elements the integers will lie +within these two elements, inclusive. By default @var{range} is +assumed to be [0:1] + +The variable @var{seed} allows the random number generator to be seeded +with a fixed value. The initial seed will be restored when returning +@end deftypefn + + + +@node randintrlv, randsrc, randint, Function Reference +@subsection randintrlv + +@deftypefn {Function File} {@var{intrlvd} =} randintrlv (@var{data}, @var{state}) +Interleaves elements of @var{data} with a random permutation +See also: intrlv, deintrlv +@end deftypefn + + + +@node randsrc, rank, randintrlv, Function Reference +@subsection randsrc + +@deftypefn {Function File} {@var{b} =} randsrc (@var{n}) +@deftypefnx {Function File} {@var{b} =} randsrc (@var{n}, @var{m}) +@deftypefnx {Function File} {@var{b} =} randsrc (@var{n}, @var{m}, @var{alphabet}) +@deftypefnx {Function File} {@var{b} =} randsrc (@var{n}, @var{m}, @var{alphabet}, @var{seed}) + +Generate a matrix of random symbols. The size of the matrix is +@var{n} rows by @var{m} columns. By default @var{m} is equal to @var{n} + +The variable @var{alphabet} can be either a row vector or a matrix with +two rows. When @var{alphabet} is a row vector the symbols returned in +@var{b} are chosen with equal probability from @var{alphabet}. When +@var{alphabet} has two rows, the second row determines the probability +with which each of the symbols is chosen. The sum of the probabilities +must equal 1. By default @var{alphabet} is [-1 1] + +The variable @var{seed} allows the random number generator to be seeded +with a fixed value. The initial seed will be restored when returning +@end deftypefn + + + +@node rank, rcosfir, randsrc, Function Reference +@subsection rank + +@deftypefn {Loadable Function} {@var{d} =} rank (@var{a}) +Compute the rank of the Galois array @var{a} by counting the independent +rows and columns +@end deftypefn + + + +@node rcosfir, reedmullerdec, rank, Function Reference +@subsection rcosfir + +@deftypefn {Function File} {@var{h}, @var{st} =} rcosfir(@var{R},@var{nT},@var{rate},@var{T},@var{filterType}) + +Implements a cosine filter or root cosine filter impulse response + +@var{R} Roll-off factor + +@var{nT} scalar vector of length 2 such as N = (nT(2)-nT(1))*rate+1 + +@var{T} symbol rate + +@var{filterType} 'normal' or 'sqrt' + +@var{h} impulse response + +@var{st} sampling interval + +Example: + +h = rcosfir(0.2,[-3 3],4,1,'sqrt'); +See also: filter, downsample, rectfilt +@end deftypefn + + + +@node reedmullerdec, reedmullerenc, rcosfir, Function Reference +@subsection reedmullerdec + +@deftypefn {Function File} {} reedmullerdec (@var{VV}, @var{G}, @var{R}, @var{M}) + +Decode the received code word @var{VV} using the RM-generator matrix @var{G}, +of order @var{R}, @var{M}, returning the code-word C. We use the standard +majority logic vote method due to Irving S. Reed. The received word has to be +a matrix of column size equal to to code-word size (i.e @math{2^m}). Each row +is treated as a separate received word + +The second return value is the message @var{M} got from @var{C} + +G is obtained from definition type construction of Reed-Muller code, +of order @var{R}, length @math{2^M}. Use the function reedmullergen, +for the generator matrix for the (@var{R},@var{M}) order RM code + +Faster code constructions (also easier) exist, but since +finding permutation order of the basis vectors, is important, we +stick with the standard definitions. To use decoder +function reedmullerdec, you need to use this specific +generator function + +see: Lin & Costello, Ch.4, "Error Control Coding", 2nd Ed, Pearson + +@example +@group +g = reedmullergen (2, 4); +msg = rand (1, 11) > 0.5; +c = mod (msg * g, 2); +[dec_c, dec_m] = reedmullerdec (c, g, 2, 4) +@end group +@end example +See also: reedmullergen, reedmullerenc +@end deftypefn + + + +@node reedmullerenc, reedmullergen, reedmullerdec, Function Reference +@subsection reedmullerenc + +@deftypefn {Function File} {} reedmullerenc (@var{MSG}, @var{R}, @var{M}) + +Definition type construction of Reed-Muller code, +of order @var{R}, length @math{2^M}. This function +returns the generator matrix for the said order RM code + +Encodes the given message word/block, of column size k, +corresponding to the RM(@var{R},@var{M}), and outputs a +code matrix @var{C}, on each row with corresponding codeword +The second return value is the @var{G}, which is generator matrix +used for this code + +@example +@group +msg = rand (10, 11) > 0.5; +[c, g] = reedmullerenc (msg, 2, 4); +@end group +@end example +See also: reedmullerdec, reedmullergen +@end deftypefn + + + +@node reedmullergen, reshape, reedmullerenc, Function Reference +@subsection reedmullergen + +@deftypefn {Function File} {} reedmullergen (@var{R}, @var{M}) + +Definition type construction of Reed-Muller code, +of order @var{R}, length @math{2^M}. This function +returns the generator matrix for the said order RM code + +RM(r,m) codes are characterized by codewords, +@code{sum ( (m,0) + (m,1) + @dots{} + (m,r)} +Each of the codeword is got through spanning the +space, using the finite set of m-basis codewords +Each codeword is @math{2^M} elements long +see: Lin & Costello, "Error Control Coding", 2nd Ed + +Faster code constructions (also easier) exist, but since +finding permutation order of the basis vectors, is important, we +stick with the standard definitions. To use decoder +function reedmullerdec, you need to use this specific +generator function + +@example +@group +g = reedmullergen (2, 4); +@end group +@end example +See also: reedmullerdec, reedmullerenc +@end deftypefn + + + +@node reshape, ricedeco, reedmullergen, Function Reference +@subsection reshape + +@deftypefn {Loadable Function} {} reshape (@var{a}, @var{m}, @var{n}) +Return a matrix with @var{m} rows and @var{n} columns whose elements are +taken from the Galois array @var{a}. To decide how to order the elements, +Octave pretends that the elements of a matrix are stored in column-major +order (like Fortran arrays are stored) + +For example, + +@example +reshape (gf ([1, 2, 3, 4], 3), 2, 2) +ans = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 1 3 + 2 4 + +@end example + +The @code{reshape} function is equivalent to + +@example +@group +retval = gf (zeros (m, n), a.m, a.prim_poly); +retval(:) = a; +@end group +@end example + +@noindent +but it is somewhat less cryptic to use @code{reshape} instead of the +colon operator. Note that the total number of elements in the original +matrix must match the total number of elements in the new matrix +See also: : +@end deftypefn + + + +@node ricedeco, riceenco, reshape, Function Reference +@subsection ricedeco + +@deftypefn {Function File} {} ricedeco (@var{code}, @var{K}) + +Returns the Rice decoded signal vector using @var{code} and @var{K} +Compulsory K is need to be specified +A restrictions is that a signal set must strictly be non-negative +The value of code is a cell array of row-vectors which have the +encoded rice value for a single sample. The Rice algorithm is + used to encode the "code" and only that can be meaningfully +decoded. @var{code} is assumed to have been of format generated +by the function @code{riceenco} + +Reference: Solomon Golomb, Run length Encodings, 1966 IEEE Trans Info Theory + +An example of the use of @code{ricedeco} is +@example +@group +ricedeco (riceenco (1:4, 2), 2) + @result{} [1 2 3 4] +@end group +@end example +See also: riceenco +@end deftypefn + + + +@node riceenco, rledeco, ricedeco, Function Reference +@subsection riceenco + +@deftypefn {Function File} {} riceenco (@var{sig}, @var{K}) + +Returns the Rice encoded signal using @var{K} or optimal K +Default optimal K is chosen between 0-7. Currently no other way +to increase the range except to specify explicitly. Also returns +@var{K} parameter used (in case it were to be chosen optimally) +and @var{Ltot} the total length of output code in bits +This function uses a @var{K} if supplied or by default chooses +the optimal K for encoding signal vector into a rice coded vector +A restrictions is that a signal set must strictly be non-negative +The Rice algorithm is used to encode the data into unary coded +quotient part which is represented as a set of 1's separated from +the K-part (binary) using a zero. This scheme doesn't need any +kind of dictionaries and its close to O(N), but this implementation +*may be* sluggish, though correct + +Reference: Solomon Golomb, Run length Encodings, 1966 IEEE Trans +Info' Theory + +An example of the use of @code{riceenco} is +@example +@group +riceenco (1:4) + @result{} @{[0 1], [1 0 0], [1 0 1], [1 1 0 0]@} +riceenco (1:10, 2) + @result{} @{[0 0 1], [0 1 0], [0 1 1], [1 0 0 0], + [1 0 0 1], [1 0 1 0], [1 0 1 1], [1 1 0 0 0], + [1 1 0 0 1], [1 1 0 1 0]@} +@end group +@end example +See also: ricedeco +@end deftypefn + + + +@node rledeco, rleenco, riceenco, Function Reference +@subsection rledeco + +@deftypefn {Function File} {} rledeco (@var{message}) + +Returns decoded run-length @var{message}. The RLE encoded @var{message} +has to be in the form of a row-vector. The message format (encoded RLE) +is like repetition [factor, value]+ + +An example use of @code{rledeco} is +@example +@group +message = [1 5 2 4 3 1]; +rledeco (message) + @result{} [5 4 4 1 1 1] +@end group +@end example +See also: rledeco +@end deftypefn + + + +@node rleenco, roots, rledeco, Function Reference +@subsection rleenco + +@deftypefn {Function File} {} rleenco (@var{message}) + +Returns run-length encoded @var{message}. The RLE form is built from +@var{message}. The original @var{message} has to be in the form of a +row-vector. The encoded @var{message} format (encoded RLE) is like +[repetition factor]+, values + +An example use of @code{rleenco} is +@example +@group +message = [5 4 4 1 1 1] +rleenco (message) + @result{} [1 5 2 4 3 1]; +@end group +@end example +See also: rleenco +@end deftypefn + + + +@node roots, rsdec, rleenco, Function Reference +@subsection roots + +@deftypefn {Function File} {} roots (@var{v}) + +For a vector @var{v} with @math{N} components, return +the roots of the polynomial over a Galois Field +@tex +$$ +v_1 z^{N-1} + \cdots + v_{N-1} z + v_N +$$ +@end tex +@ifnottex + +@example +v(1) * z^(N-1) + ... + v(N-1) * z + v(N) +@end example +@end ifnottex + +The number of roots returned and their value will be determined +by the order and primitive polynomial of the Galois Field +@end deftypefn + + + +@node rsdec, rsdecof, roots, Function Reference +@subsection rsdec + +@deftypefn {Loadable Function} {@var{msg} =} rsdec (@var{code}, @var{n}, @var{k}) +@deftypefnx {Loadable Function} {@var{msg} =} rsdec (@var{code}, @var{n}, @var{k}, @var{g}) +@deftypefnx {Loadable Function} {@var{msg} =} rsdec (@var{code}, @var{n}, @var{k}, @var{fcr}, @var{prim}) +@deftypefnx {Loadable Function} {@var{msg} =} rsdec (@dots{}, @var{parpos}) +@deftypefnx {Loadable Function} {[@var{msg}, @var{nerr}] =} rsdec (@dots{}) +@deftypefnx {Loadable Function} {[@var{msg}, @var{nerr}, @var{ccode}] =} rsdec (@dots{}) +Decodes the message contained in @var{code} using a [@var{n},@var{k}] +Reed-Solomon code. The variable @var{code} must be a Galois array with +@var{n} columns and an arbitrary number of rows. Each row of @var{code} +represents a single block to be decoded by the Reed-Solomon coder. The +decoded message is returned in the variable @var{msg} containing @var{k} +columns and the same number of rows as @var{code}. + +If @var{n} does not equal @code{2^@var{m}-1}, where m is an integer, then a +shorten Reed-Solomon decoding is used where zeros are added to the start of +each row to obtain an allowable codeword length. The returned @var{msg} +has these prepending zeros stripped. + +By default the generator polynomial used in the Reed-Solomon coding is based +on the properties of the Galois Field in which @var{msg} is given. This +default generator polynomial can be overridden by a polynomial in @var{g}. +Suitable generator polynomials can be constructed with @code{rsgenpoly}. +@var{fcr} is an integer value, and it is taken to be the first consecutive +root of the generator polynomial. The variable @var{prim} is then the +primitive element used to construct the generator polynomial. By default +@var{fcr} and @var{prim} are both 1. It is significantly faster to specify +the generator polynomial in terms of @var{fcr} and @var{prim}, since @var{g} +is converted to this form in any case. + +By default the parity symbols are placed at the end of the coded message. +The variable @var{parpos} controls this positioning and can take the values +@code{"beginning\"} or @code{\"end\"}. If the parity symbols are at the end, the message is +treated with the most-significant symbol first, otherwise the message is +treated with the least-significant symbol first. +See also: gf, rsenc, rsgenpoly +@end deftypefn + + + +@node rsdecof, rsenc, rsdec, Function Reference +@subsection rsdecof + +@deftypefn {Function File} {} rsdecof (@var{in}, @var{out}) +@deftypefnx {Function File} {} rsdecof (@var{in}, @var{out}, @var{t}) + +Decodes an ASCII file using a Reed-Solomon coder. The input file is +defined by @var{in} and the result is written to the output file @var{out} +The type of coding to use is determined by whether the input file is 7- +or 8-bit. If the input file is 7-bit, the default coding is [127,117] +while the default coding for an 8-bit file is a [255, 235]. This allows +for 5 or 10 error characters in 127 or 255 symbols to be corrected +respectively. The number of errors that can be corrected can be overridden +by the variable @var{t} + +If the file is not an integer multiple of the message size (127 or 255) +in length, then the file is padded with the EOT (ASCII character 4) +character before decoding + +See also: rsencof +@end deftypefn + + + +@node rsenc, rsencof, rsdecof, Function Reference +@subsection rsenc + +@deftypefn {Loadable Function} {@var{code} =} rsenc (@var{msg}, @var{n}, @var{k}) +@deftypefnx {Loadable Function} {@var{code} =} rsenc (@var{msg}, @var{n}, @var{k}, @var{g}) +@deftypefnx {Loadable Function} {@var{code} =} rsenc (@var{msg}, @var{n}, @var{k}, @var{fcr}, @var{prim}) +@deftypefnx {Loadable Function} {@var{code} =} rsenc (@dots{}, @var{parpos}) +Encodes the message @var{msg} using a [@var{n},@var{k}] Reed-Solomon coding. +The variable @var{msg} is a Galois array with @var{k} columns and an arbitrary +number of rows. Each row of @var{msg} represents a single block to be coded +by the Reed-Solomon coder. The coded message is returned in the Galois +array @var{code} containing @var{n} columns and the same number of rows as +@var{msg}. + +The use of @code{rsenc} can be seen in the following short example. + +@example +m = 3; n = 2^m -1; k = 3; +msg = gf ([1 2 3; 4 5 6], m); +code = rsenc (msg, n, k); +@end example + +If @var{n} does not equal @code{2^@var{m}-1}, where m is an integer, then a +shorten Reed-Solomon coding is used where zeros are added to the start of +each row to obtain an allowable codeword length. The returned @var{code} +has these prepending zeros stripped. + +By default the generator polynomial used in the Reed-Solomon coding is based +on the properties of the Galois Field in which @var{msg} is given. This +default generator polynomial can be overridden by a polynomial in @var{g}. +Suitable generator polynomials can be constructed with @code{rsgenpoly}. +@var{fcr} is an integer value, and it is taken to be the first consecutive +root of the generator polynomial. The variable @var{prim} is then the +primitive element used to construct the generator polynomial, such that +@tex +$g = (x - A^b) (x - A^{b+p}) \cdots (x - A ^{b+2tp-1})$. +@end tex +@ifnottex + +@var{g} = (@var{x} - A^@var{b}) * (@var{x} - A^(@var{b}+@var{prim})) * ... * (@var{x} - A^(@var{b}+2*@var{t}*@var{prim}-1)). +@end ifnottex + +where @var{b} is equal to @code{@var{fcr} * @var{prim}}. By default @var{fcr} +and @var{prim} are both 1. + +By default the parity symbols are placed at the end of the coded message. +The variable @var{parpos} controls this positioning and can take the values +@code{"beginning\"} or @code{\"end\"}. +See also: gf, rsdec, rsgenpoly +@end deftypefn + + + +@node rsencof, rsgenpoly, rsenc, Function Reference +@subsection rsencof + +@deftypefn {Function File} {} rsencof (@var{in}, @var{out}) +@deftypefnx {Function File} {} rsencof (@var{in}, @var{out}, @var{t}) +@deftypefnx {Function File} {} rsencof (@dots{}, @var{pad}) + +Encodes an ASCII file using a Reed-Solomon coder. The input file is +defined by @var{in} and the result is written to the output file @var{out} +The type of coding to use is determined by whether the input file is 7- +or 8-bit. If the input file is 7-bit, the default coding is [127,117] +while the default coding for an 8-bit file is a [255, 235]. This allows +for 5 or 10 error characters in 127 or 255 symbols to be corrected +respectively. The number of errors that can be corrected can be overridden +by the variable @var{t} + +If the file is not an integer multiple of the message size (127 or 255) +in length, then the file is padded with the EOT (ASCII character 4) +characters before coding. Whether these characters are written to the +output is defined by the @var{pad} variable. Valid values for @var{pad} +are "pad" (the default) and "nopad", which write or not the padding +respectively + +See also: rsdecof +@end deftypefn + + + +@node rsgenpoly, scatterplot, rsencof, Function Reference +@subsection rsgenpoly + +@deftypefn {Function File} {@var{g} =} rsgenpoly (@var{n}, @var{k}) +@deftypefnx {Function File} {@var{g} =} rsgenpoly (@var{n}, @var{k}, @var{p}) +@deftypefnx {Function File} {@var{g} =} rsgenpoly (@var{n}, @var{k}, @var{p}, @var{b}, @var{s}) +@deftypefnx {Function File} {@var{g} =} rsgenpoly (@var{n}, @var{k}, @var{p}, @var{b}) +@deftypefnx {Function File} {[@var{g}, @var{t}] =} rsgenpoly (@dots{}) + +Creates a generator polynomial for a Reed-Solomon coding with message +length of @var{k} and codelength of @var{n}. @var{n} must be greater +than @var{k} and their difference must be even. The generator polynomial +is returned on @var{g} as a polynomial over the Galois Field GF(2^@var{m}) +where @var{n} is equal to @code{2^@var{m}-1}. If @var{m} is not integer +the next highest integer value is used and a generator for a shorten +Reed-Solomon code is returned + +The elements of @var{g} represent the coefficients of the polynomial in +descending order. If the length of @var{g} is lg, then the generator +polynomial is given by +@tex +$$ +g_0 x^{lg-1} + g_1 x^{lg-2} + \cdots + g_{lg-1} x + g_lg +$$ +@end tex +@ifnottex + +@example +@var{g}(0) * x^(lg-1) + @var{g}(1) * x^(lg-2) + ... + @var{g}(lg-1) * x + @var{g}(lg) +@end example +@end ifnottex + +If @var{p} is defined then it is used as the primitive polynomial of the +Galois Field GF(2^@var{m}). The default primitive polynomial will be used +if @var{p} is equal to [] + +The variables @var{b} and @var{s} determine the form of the generator +polynomial in the following manner +@tex +$$ +g = (x - A^{bs}) (x - A^{(b+1)s}) \cdots (x - A ^{(b+2t-1)s}) +$$ +@end tex +@ifnottex + +@example +@var{g} = (@var{x} - A^(@var{b}*@var{s})) * (@var{x} - A^((@var{b}+1)*@var{s})) * ... * (@var{x} - A^((@var{b}+2*@var{t}-1)*@var{s})) +@end example +@end ifnottex + +where @var{t} is @code{(@var{n}-@var{k})/2}, and A is the primitive element +of the Galois Field. Therefore @var{b} is the first consecutive root of the +generator polynomial and @var{s} is the primitive element to generate the +polynomial roots + +If requested the variable @var{t}, which gives the error correction +capability of the Reed-Solomon code +See also: gf, rsenc, rsdec +@end deftypefn + + + +@node scatterplot, shannonfanodeco, rsgenpoly, Function Reference +@subsection scatterplot + +@deftypefn {Function File} {} scatterplot (@var{x}) +@deftypefnx {Function File} {} scatterplot (@var{x}, @var{n}) +@deftypefnx {Function File} {} scatterplot (@var{x}, @var{n}, @var{off}) +@deftypefnx {Function File} {} scatterplot (@var{x}, @var{n}, @var{off}, @var{str}) +@deftypefnx {Function File} {} scatterplot (@var{x}, @var{n}, @var{off}, @var{str}, @var{h}) +@deftypefnx {Function File} {@var{h} =} scatterplot (@dots{}) + +Display the scatter plot of a signal. The signal @var{x} can be either in +one of three forms + +@table @asis +@item A real vector +In this case the signal is assumed to be real and represented by the vector +@var{x}. The scatterplot is plotted along the x axis only +@item A complex vector +In this case the in-phase and quadrature components of the signal are +plotted separately on the x and y axes respectively +@item A matrix with two columns +In this case the first column represents the in-phase and the second the +quadrature components of a complex signal and are plotted on the x and +y axes respectively +@end table + +Each point of the scatter plot is assumed to be separated by @var{n} +elements in the signal. The first element of the signal to plot is +determined by @var{off}. By default @var{n} is 1 and @var{off} is 0 + +The string @var{str} is a plot style string (example "r+"), +and by default is the default gnuplot point style + +The figure handle to use can be defined by @var{h}. If @var{h} is not +given, then the next available figure handle is used. The figure handle +used in returned on @var{hout} +See also: eyediagram +@end deftypefn + + + +@node shannonfanodeco, shannonfanodict, scatterplot, Function Reference +@subsection shannonfanodeco + +@deftypefn {Function File} {} shannonfanodeco (@var{hcode}, @var{dict}) + +Returns the original signal that was Shannon-Fano encoded. The signal +was encoded using @code{shannonfanoenco}. This function uses +a dict built from the @code{shannonfanodict} and uses it to decode a signal +list into a Shannon-Fano list. Restrictions include hcode is expected to be a binary code; +returned signal set that strictly belongs in the @code{range [1,N]}, +with @code{N = length (dict)}. Also dict can only be from the +@code{shannonfanodict (...)} routine. Whenever decoding fails, +those signal values are indicated by -1, and we successively +try to restart decoding from the next bit that hasn't failed in +decoding, ad-infinitum + +An example use of @code{shannonfanodeco} is +@example +@group +hd = shannonfanodict (1:4, [0.5 0.25 0.15 0.10]); +hcode = shannonfanoenco (1:4, hd) + @result{} hcode = [0 1 0 1 1 0 1 1 1 0] +shannonfanodeco (hcode, hd) + @result{} [1 2 3 4] +@end group +@end example +See also: shannonfanoenco, shannonfanodict +@end deftypefn + + + +@node shannonfanodict, shannonfanoenco, shannonfanodeco, Function Reference +@subsection shannonfanodict + +@deftypefn {Function File} {} shannonfanodict (@var{symbols}, @var{symbol_probabilites}) + +Returns the code dictionary for source using Shannon-Fano algorithm +Dictionary is built from @var{symbol_probabilities} using the +Shannon-Fano scheme. Output is a dictionary cell-array, which +are codewords, and correspond to the order of input probability + +@example +@group +cw = shannonfanodict (1:4, [0.5 0.25 0.15 0.1]); +assert (redundancy (cw, [0.5 0.25 0.15 0.1]), 0.25841, 0.001) +shannonfanodict (1:5, [0.35 0.17 0.17 0.16 0.15]) +shannonfanodict (1:8, [8 7 6 5 5 4 3 2] / 40) +@end group +@end example +See also: shannonfanoenc, shannonfanodec +@end deftypefn + + + +@node shannonfanoenco, sqrt, shannonfanodict, Function Reference +@subsection shannonfanoenco + +@deftypefn {Function File} {} shannonfanoenco (@var{hcode}, @var{dict}) + +Returns the Shannon-Fano encoded signal using @var{dict} +This function uses a @var{dict} built from the @code{shannonfanodict} +and uses it to encode a signal list into a Shannon-Fano code +Restrictions include a signal set that strictly belongs in the +@code{range [1,N]} with @code{N = length (dict)}. Also dict can only be +from the @code{shannonfanodict} routine +An example use of @code{shannonfanoenco} is + +@example +@group +hd = shannonfanodict (1:4, [0.5 0.25 0.15 0.10]); +shannonfanoenco (1:4, hd) + @result{} [0 1 0 1 1 0 1 1 1 0] +@end group +@end example +See also: shannonfanodeco, shannonfanodict +@end deftypefn + + + +@node sqrt, sum, shannonfanoenco, Function Reference +@subsection sqrt + +@deftypefn {Loadable Function} {} sqrt (@var{x}) +Compute the square root of @var{x}, element by element, in a Galois Field +See also: exp +@end deftypefn + + + +@node sum, sumsq, sqrt, Function Reference +@subsection sum + +@deftypefn {Loadable Function} {} sum (@var{x}, @var{dim}) +Sum of elements along dimension @var{dim} of Galois array. If @var{dim} +is omitted, it defaults to 1 (column-wise sum) +@end deftypefn + + + +@node sumsq, symerr, sum, Function Reference +@subsection sumsq + +@deftypefn {Loadable Function} {} sumsq (@var{x}, @var{dim}) +Sum of squares of elements along dimension @var{dim} of Galois array +If @var{dim} is omitted, it defaults to 1 (column-wise sum of squares) + +This function is equivalent to computing +@example +gsum (x .* conj (x), dim) +@end example +but it uses less memory +@end deftypefn + + + +@node symerr, syndtable, sumsq, Function Reference +@subsection symerr + +@deftypefn {Function File} {[@var{num}, @var{rate}] =} symerr (@var{a}, @var{b}) +@deftypefnx {Function File} {[@var{num}, @var{rate}] =} symerr (@dots{}, @var{flag}) +@deftypefnx {Function File} {[@var{num}, @var{rate} @var{ind}] =} symerr (@dots{}) + +Compares two matrices and returns the number of symbol errors and the +symbol error rate. The variables @var{a} and @var{b} can be either: + +@table @asis +@item Both matrices +In this case both matrices must be the same size and then by default the +return values @var{num} and @var{rate} are the overall number of symbol +errors and the overall symbol error rate +@item One column vector +In this case the column vector is used for symbol error comparison +column-wise with the matrix. The returned values @var{num} and @var{rate} +are then row vectors containing the number of symbol errors and the symbol +error rate for each of the column-wise comparisons. The number of rows in +the matrix must be the same as the length of the column vector +@item One row vector +In this case the row vector is used for symbol error comparison row-wise +with the matrix. The returned values @var{num} and @var{rate} are then +column vectors containing the number of symbol errors and the symbol error +rate for each of the row-wise comparisons. The number of columns in the +matrix must be the same as the length of the row vector +@end table + +This behavior can be overridden with the variable @var{flag}. @var{flag} +can take the value "column-wise", "row-wise" or "overall". A column-wise +comparison is not possible with a row vector and visa-versa +@end deftypefn + + + +@node syndtable, systematize, symerr, Function Reference +@subsection syndtable + +@deftypefn {Loadable Function} {@var{t} =} syndtable (@var{h}) +Create the syndrome decoding table from the parity check matrix @var{h}. +Each row of the returned matrix @var{t} represents the error vector in +a received symbol for a certain syndrome. The row selected is determined +by a conversion of the syndrome to an integer representation, and using +this to reference each row of @var{t}. +See also: hammgen, cyclgen +@end deftypefn + + + +@node systematize, vec2mat, syndtable, Function Reference +@subsection systematize + +@deftypefn {Function File} {} systematize (@var{G}) + +Given @var{G}, extract P parity check matrix. Assume row-operations in GF(2) +@var{G} is of size KxN, when decomposed through row-operations into a @var{I} of size KxK +identity matrix, and a parity check matrix @var{P} of size Kx(N-K) + +Most arbitrary code with a given generator matrix @var{G}, can be converted into its +systematic form using this function + +This function returns 2 values, first is default being @var{Gx} the systematic version of +the @var{G} matrix, and then the parity check matrix @var{P} + +@example +@group +g = [1 1 1 1; 1 1 0 1; 1 0 0 1]; +[gx, p] = systematize (g); + @result{} gx = [1 0 0 1; 0 1 0 0; 0 0 1 0]; + @result{} p = [1 0 0]; +@end group +@end example +See also: bchpoly, biterr +@end deftypefn + + + +@node vec2mat, wgn, systematize, Function Reference +@subsection vec2mat + +@deftypefn {Function File} {@var{m} =} vec2mat (@var{v}, @var{c}) +@deftypefnx {Function File} {@var{m} =} vec2mat (@var{v}, @var{c}, @var{d}) +@deftypefnx {Function File} {[@var{m}, @var{add}] =} vec2mat (@dots{}) + +Converts the vector @var{v} into a @var{c} column matrix with row priority +arrangement and with the final column padded with the value @var{d} to the +correct length. By default @var{d} is 0. The amount of padding added to +the matrix is returned in @var{add} +@end deftypefn + + + +@node wgn, , vec2mat, Function Reference +@subsection wgn + +@deftypefn {Function File} {@var{y} =} wgn (@var{m}, @var{n}, @var{p}) +@deftypefnx {Function File} {@var{y} =} wgn (@var{m}, @var{n}, @var{p}, @var{imp}) +@deftypefnx {Function File} {@var{y} =} wgn (@var{m}, @var{n}, @var{p}, @var{imp}, @var{seed}) +@deftypefnx {Function File} {@var{y} =} wgn (@dots{}, @var{type}) +@deftypefnx {Function File} {@var{y} =} wgn (@dots{}, @var{output}) + +Returns a M-by-N matrix @var{y} of white Gaussian noise. @var{p} specifies +the power of the output noise, which is assumed to be referenced to an +impedance of 1 Ohm, unless @var{imp} explicitly defines the impedance + +If @var{seed} is defined then the randn function is seeded with this +value + +The arguments @var{type} and @var{output} must follow the above numerical +arguments, but can be specified in any order. @var{type} specifies the +units of @var{p}, and can be "dB", "dBW", "dBm" or "linear". "dB" is +in fact the same as "dBW" and is keep as a misnomer of Matlab. The +units of "linear" are in Watts + +The @var{output} variable should be either "real" or "complex". If the +output is complex then the power @var{p} is divided equally between the +real and imaginary parts + +See also: randn, awgn +@end deftypefn + + + +@bye diff --git a/doc/comms.txi b/doc/comms.txi new file mode 100644 index 0000000..9088de9 --- /dev/null +++ b/doc/comms.txi @@ -0,0 +1,2310 @@ +\input texinfo + +@setfilename comms.info + +@settitle Communications Package for Octave + +@titlepage +@title Communications Package for Octave +@subtitle November 2013 +@author David Bateman +@author Paul Kienzle +@author Laurent Mazet +@author Mike Miller +@page +@vskip 0pt plus 1filll +Copyright @copyright{} 2003-2013 + +Permission is granted to make and distribute verbatim copies of +this manual provided the copyright notice and this permission notice +are preserved on all copies. + +Permission is granted to copy and distribute modified versions of this +manual under the conditions for verbatim copying, provided that the entire +resulting derived work is distributed under the terms of a permission +notice identical to this one. + +Permission is granted to copy and distribute translations of this manual +into another language, under the same conditions as for modified versions. +@end titlepage + +@contents + +@ifnottex +@node Top, Introduction +@top +@end ifnottex + +@menu +* Introduction:: +* Random Signals:: +* Source Coding:: +* Block Coding:: +* Convolutional Coding:: +* Modulations:: +* Special Filters:: +* Galois Fields:: +* Function Reference:: +@end menu + +@node Introduction, Random Signals, Top, Top +@chapter Introduction + +This is the manual for the Communications Package for GNU Octave. All +functions provided by this package are described in this manual. In addition +many functions from Octave and other Octave packages are useful to or +required by this package, and so they may also be explained or shown in +examples in this manual. + +This documentation is a work in progress, you are invited to help improve it +and submit patches. + +@node Random Signals, Source Coding, Introduction, Top +@chapter Random Signals + +The purpose of the functions described here is to create and add random +noise to a signal, to create random data and to analyze the eventually +errors in a received signal. The functions to perform these tasks can +be considered as either related to the creation or analysis of signals +and are treated separately below. + +It should be noted that the examples below are based on the output of a +random number generator, and so the user can not expect to exactly recreate +the examples below. + +@menu +* Signal Creation:: +* Signal Analysis:: +@end menu + +@node Signal Creation, Signal Analysis, , Random Signals +@section Signal Creation + +The signal creation functions here fall into to two classes. Those that +treat discrete data and those that treat continuous data. The basic +function to create discrete data is @code{randint}, that creates a +random matrix of equi-probable integers in a desired range. For example + +@example +octave:1> a = randint (3, 3, [-1, 1]) +a = + + 0 1 0 + -1 -1 1 + 0 1 1 +@end example + +@noindent +creates a 3-by-3 matrix of random integers in the range -1 to 1. To allow +for repeated analysis with the same random data, the function @code{randint} +allows the seed-value of the random number generator to be set. For instance + +@example +octave:1> a = randint (3, 3, [-1, 1], 1) +a = + + 0 1 1 + 0 -1 0 + 1 -1 -1 +@end example + +@noindent +will always produce the same set of random data. The range of the integers +to produce can either be a two element vector or an integer. In the case +of a two element vector all elements within the defined range can be produced. +In the case of an integer range @var{M}, @code{randint} returns the equi-probable +integers in the range +@tex +$[0:2^m-1]$. +@end tex +@ifnottex +[0:2^@var{m}-1]. +@end ifnottex + +The function @code{randsrc} differs from @code{randint} in that it allows +a random set of symbols to be created with a given probability. The symbols +can be real, complex or even characters. However characters and scalars +can not be mixed. For example + +@example +octave:1> a = randsrc (2, 2, "ab"); +octave:2> b = randsrc (4, 4, [1, 1i, -1, -1i]); +@end example + +@noindent +are both legal, while + +@example +octave:1> a = randsrc (2, 2, [1, "a"]); +@end example + +@noindent +is not legal. The alphabet from which the symbols are chosen can be either +a row vector or two row matrix. In the case of a row vector, all of the +elements of the alphabet are chosen with an equal probability. In the case +of a two row matrix, the values in the second row define the probability +that each of the symbols are chosen. For example + +@example +octave:1> a = randsrc (5, 5, [1, 1i, -1, -1i; 0.6 0.2 0.1 0.1]) +a = + + 1 + 0i 0 + 1i 0 + 1i 0 + 1i 1 + 0i + 1 + 0i 1 + 0i 0 + 1i 0 + 1i 1 + 0i + -0 - 1i 1 + 0i -1 + 0i 1 + 0i 0 + 1i + 1 + 0i 1 + 0i 1 + 0i 1 + 0i 1 + 0i + -1 + 0i -1 + 0i 1 + 0i 1 + 0i 1 + 0i +@end example + +@noindent +defines that the symbol '1' has a 60% probability, the symbol '1i' has +a 20% probability and the remaining symbols have 10% probability each. +The sum of the probabilities must equal one. Like @code{randint}, +@code{randsrc} accepts a fourth argument as the seed of the random +number generator allowing the same random set of data to be reproduced. + +The function @code{randerr} allows a matrix of random bit errors to be +created, for binary encoded messages. By default, @code{randerr} creates +exactly one errors per row, flagged by a non-zero value in the returned +matrix. That is + +@example +octave:1> a = randerr (5, 10) +a = + + 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 1 + 0 0 0 0 0 0 0 0 0 1 +@end example + +The number of errors per row can be specified as the third argument to +@code{randerr}. This argument can be either a scalar, a row vector or +a two row matrix. In the case of a scalar value, exactly this number of +errors will be created per row in the returned matrix. In the case of +a row vector, each element of the row vector gives a possible number of +equi-probable bit errors. The second row of a two row matrix defines +the probability of each number of errors occurring. For example + +@example +octave:1> n = 15; k = 11; nsym = 100; +octave:2> msg = randint (nsym, k); ## Binary vector of message +octave:3> code = encode (msg, n, k, "bch"); +octave:4> berrs = randerr (nsym, n, [0, 1; 0.7, 0.3]); +octave:5> noisy = mod (code + berrs, 2) ## Add errors to coded message +@end example + +@noindent +creates a vector @var{msg}, encodes it with a [15,11] BCH code, and then +add either none or one error per symbol with the chances of an error being +30%. As previously, @code{randerr} accepts a fourth argument as the seed of +the random number generator allowing the same random set of data to be +reproduced. + +All of the above functions work on discrete random signals. The functions +@code{wgn} and @code{awgn} create and add white Gaussian noise to continuous +signals. The function @code{wgn} creates a matrix of white Gaussian noise +of a certain power. A typical call to @code{wgn} is then + +@example +octave:1> nse = wgn (10, 10, 0); +@end example + +@noindent +which creates a 10-by-10 matrix of noise with a root mean squared power +of 0dBW relative to an impedance of +@tex +$1\Omega$. +@end tex +@ifnottex +1 Ohm. +@end ifnottex + +This effectively means that an equivalent result to the above can be +obtained with + +@example +octave:1> nse = randn (10, 10); +@end example + +The reference impedance and units of power to the function @code{wgn} +can however be modified, for example + +@example +octave:1> nse_30dBm_50Ohm = wgn (10000, 1, 30, 50, "dBm"); +octave:2> nse_0dBW_50Ohm = wgn (10000, 1, 0, 50, "dBW"); +octave:3> nse_1W_50Ohm = wgn (10000, 1, 1, 50, "linear"); +octave:4> [std(nse_30dBm_50Ohm), std(nse_0dBW_50Ohm), std(nse_1W_50Ohm)] +ans = + + 7.0805 7.1061 7.0730 +@end example + +Each of these produces a 1W signal referenced to a +@tex +$50\Omega$ +@end tex +@ifnottex +50 Ohm +@end ifnottex +impedance. @sc{matlab} uses the misnomer "dB" for "dBW", so "dB" is an +accepted type for @code{wgn} and is treated as a synonym for "dBW". + +In all cases, the returned matrix @var{v}, will be related to the input +power @var{p} and the impedance @var{Z} as + +@tex +$$p = {\\sum_i \\sum_j v(i,j)^2 \\over Z} Watts$$ +@end tex +@ifnottex +@var{p} = sum (@var{v}(:) .^ 2 ) / @var{imp} Watts +@end ifnottex + +By default @code{wgn} produces real vectors of white noise. However, it can +produce both real and complex vectors like + +@example +octave:1> rnse = wgn (10000, 1, 0, "dBm", "real"); +octave:2> cnse = wgn (10000, 1, 0, "dBm", "complex"); +octave:3> [std(rnse), std(real (cnse)), std(imag (cnse)), std(cnse)] +ans = + + 0.031615 0.022042 0.022241 0.031313 +@end example + +@noindent +which shows that with a complex return value that the total power is the +same as a real vector, but that it is equally shared between the real and +imaginary parts. As previously, @code{wgn} accepts a fourth numerical argument +as the seed of the random number generator allowing the same random set of +data to be reproduced. That is + +@example +octave:1> nse = wgn (10, 10, 0, 0); +@end example + +@noindent +will always produce the same set of data. + +The final function to deal with the creation of random signals is +@code{awgn}, that adds noise at a certain level relative to a desired +signal. This function adds noise at a certain level to a desired +signal. An example call to @code{awgn} is + +@example +octave:1> x = [0:0.1:2*pi]; +octave:2> y = sin (x); +octave:3> noisy = awgn (y, 10, "measured") +@end example + +@ifnotinfo +@noindent +which produces a sine-wave with noise added as seen in Figure 1. + +@center @image{awgn} + +@center Figure 1: Sine-wave with 10dB signal-to-noise ratio +@end ifnotinfo + +@noindent +which adds noise with a 10dB signal-to-noise ratio to the measured power +in the desired signal. By default @code{awgn} assumes that the desired +signal is at 0dBW, and the noise is added relative to this assumed +power. This behavior can be modified by the third argument to @code{awgn}. +If the third argument is a numerical value, it is assumed to define the +power in the input signal, otherwise if the third argument is the string +"measured", as above, the power in the signal is measured prior to the +addition of the noise. + +The final argument to @code{awgn} defines the definition of the power and +signal-to-noise ratio in a similar manner to @code{wgn}. This final +argument can be either "dB" or "linear". In the first case the numerical +value of the input power is assumed to be in dBW and the signal-to-noise +ratio in dB. In the second case, the power is assumed to be in Watts +and the signal-to-noise ratio is expressed as a ratio. + +The return value of @code{awgn} will be in the same form as the input +signal. In addition if the input signal is real, the additive noise will +be real. Otherwise the additive noise will also be complex and the noise +will be equally split between the real and imaginary parts. + +As previously the seed to the random number generator can be specified +as the last argument to @code{awgn} to allow repetition of the same +scenario. That is + +@example +octave:1> x = [0:0.1:2*pi]; +octave:2> y = sin (x); +octave:3> noisy = awgn (y, 10, "dB", 0, "measured") +@end example + +@noindent +which uses the seed-value of 0 for the random number generator. + +@node Signal Analysis, , Signal Creation, Random Signals +@section Signal Analysis + +It is important to be able to evaluate the performance of a +communications system in terms of its bit-error and symbol-error +rates. Two functions @code{biterr} and @code{symerr} exist within this +package to calculate these values, both taking as arguments the +expected and the actually received data. The data takes the form +of matrices or vectors, with each element representing a single +symbol. They are compared in the following manner + +@table @asis +@item Both matrices +In this case both matrices must be the same size and then by default the +return values are the overall number of errors and the overall error rate. +@item One column vector +In this case the column vector is used for comparison column-wise +with the matrix. The return values are row vectors containing the number +of errors and the error rate for each column-wise comparison. The number +of rows in the matrix must be the same as the length of the column vector. +@item One row vector +In this case the row vector is used for comparison row-wise +with the matrix. The return values are column vectors containing the number +of errors and the error rate for each row-wise comparison. The number +of columns in the matrix must be the same as the length of the row vector. +@end table + +For the bit-error comparison, the size of the symbol is assumed to be the +minimum number of bits needed to represent the largest element in the +two matrices supplied. However, the number of bits per symbol can (and +in the case of random data should) be specified. As an example of the +use of @code{biterr} and @code{symerr}, consider the example + +@example +octave:1> m = 8; +octave:2> msg = randint (10, 10, 2^m); +octave:3> noisy = mod (msg + diag (1:10), 2^m); +octave:4> [berr, brate] = biterr (msg, noisy, m) +berr = 32 +brate = 0.040000 +octave:5> [serr, srate] = symerr (msg, noisy) +serr = 10 +srate = 0.10000 +@end example + +@noindent +which creates a 10-by-10 matrix adds 10 symbols errors to the data and then +finds the bit and symbol error-rates. + +Two other means of displaying the integrity of a signal are the +eye-diagram and the scatterplot. Although the functions +@code{eyediagram} and @code{scatterplot} have different appearance, the +information presented is similar and so are their inputs. The difference +between @code{eyediagram} and @code{scatterplot} is that @code{eyediagram} +segments the data into time intervals and plots the in-phase and +quadrature components of the signal against this time interval. While +@code{scatterplot} uses a parametric plot of quadrature versus in-phase +components. + +Both functions can accept real or complex signals in the following +forms. + +@table @asis +@item A real vector +In this case the signal is assumed to be real and represented by the vector +@var{x}. +@item A complex vector +In this case the in-phase and quadrature components of the signal are +assumed to be the real and imaginary parts of the signal. +@item A matrix with two columns +In this case the first column represents the in-phase and the second the +quadrature components of a complex signal. +@end table + +An example of the use of the function @code{eyediagram} is + +@example +octave:1> n = 50; +octave:2> ovsp = 50; +octave:3> x = 1:n; +octave:4> xi = 1:1/ovsp:n-0.1; +octave:5> y = randsrc (1, n, [1 + 1i, 1 - 1i, -1 - 1i, -1 + 1i]); +octave:6> yi = interp1 (x, y, xi); +octave:7> noisy = awgn (yi, 15, "measured"); +octave:8> eyediagram (noisy, ovsp); +@end example + +@ifnotinfo +@noindent +which produces a eye-diagram of a noisy signal as seen in Figure 2. Similarly +an example of the use of the function @code{scatterplot} is + +@center @image{eyediagram} + +@center Figure 2: Eye-diagram of a QPSK like signal with 15dB signal-to-noise ratio +@end ifnotinfo +@ifinfo +Similarly an example of the use of the function @code{scatterplot} is +@end ifinfo + +@example +octave:1> n = 200; +octave:2> ovsp = 5; +octave:3> x = 1:n; +octave:4> xi = 1:1/ovsp:n-0.1; +octave:5> y = randsrc (1, n, [1 + 1i, 1 - 1i, -1 - 1i, -1 + 1i]); +octave:6> yi = interp1 (x, y, xi); +octave:7> noisy = awgn (yi, 15, "measured"); +octave:8> f = scatterplot (noisy, 1, 0, "b"); +octave:9> hold on; +octave:10> scatterplot (noisy, ovsp, 0, "r+", f); +@end example + +@ifnotinfo +@noindent +which produces a scatterplot of a noisy signal as seen in Figure 3. + +@center @image{scatterplot} + +@center Figure 3: Scatterplot of a QPSK like signal with 15dB signal-to-noise ratio +@end ifnotinfo + +@node Source Coding, Block Coding, Random Signals, Top +@chapter Source Coding + +@menu +* Quantization:: +* PCM Coding:: +* Arithmetic Coding:: +* Dynamic Range Compression:: +@end menu + +@node Quantization, PCM Coding, , Source Coding +@section Quantization + +An important aspect of converting an analog signal to the digital domain +is quantization. This is the process of mapping a continuous signal to a +set of defined values. Octave contains two functions to perform quantization, +@code{lloyds} creates an optimal mapping of the continuous signal to a fixed +number of levels and @code{quantiz} performs the actual quantization. + +The set of quantization points to use is represented by a partitioning +table (@var{table}) of the data and the signal levels (@var{codes} to +which they are mapped. The partitioning @var{table} is monotonically +increasing and if x falls within the range given by two points of this +table then it is mapped to the corresponding code as seen in Table 1. + +@center Table 1: Table quantization partitioning and coding + +@multitable @columnfractions 0.1 0.4 0.4 0.1 +@item @tab x < table(1) @tab codes(1) @tab +@item @tab table(1) <= x < table(2) @tab codes(2) @tab +@item @tab @dots{} @tab @dots{} @tab +@item @tab table(i-1) <= x < table(i) @tab codes(i) @tab +@item @tab @dots{} @tab @dots{} @tab +@item @tab table(n-1) <= x < table(n) @tab codes(n) @tab +@item @tab table(n-1) <= x @tab codes(n+1) @tab +@end multitable + +These partition and coding tables can either be created by the user of +using the function @code{lloyds}. For instance the use of a linear +mapping can be seen in the following example. + +@example +octave:1> m = 8; +octave:2> n = 1024; +octave:3> table = 2*[0:m-1]/m - 1 + 1/m; +octave:4> codes = 2*[0:m]/m - 1; +octave:5> x = 4*pi*[0:(n-1)]/(n-1); +octave:6> y = cos (x); +octave:7> [i, z] = quantiz (y, table, codes); +@end example + +If a training signal is known that well represents the expected signals, +the quantization levels can be optimized using the @code{lloyds} function. +For example the above example can be continued + +@example +octave:8> [table2, codes2] = lloyds (y, table, codes); +octave:9> [i, z2] = quantiz (y, table2, codes2); +@end example + +@noindent +to use the mapping suggested by the function @code{lloyds}. It should be +noted that the mapping given by @code{lloyds} is highly dependent on the +training signal used. So if this signal does not represent a realistic +signal to be quantized, then the partitioning suggested by @code{lloyds} +will be sub-optimal. + +@node PCM Coding, Arithmetic Coding, Quantization, Source Coding +@section PCM Coding + +The DPCM function @code{dpcmenco}, @code{dpcmdeco} and @code{dpcmopt} +implement a form of predictive quantization, where the predictability +of the signal is used to further compress it. These functions are +not yet implemented. + +@node Arithmetic Coding, Dynamic Range Compression, PCM Coding, Source Coding +@section Arithmetic Coding + +The arithmetic coding functions @code{arithenco} and @code{arithdeco} are +not yet implemented. + +@node Dynamic Range Compression, , Arithmetic Coding, Source Coding +@section Dynamic Range Compression + +The final source coding function is @code{compand} which is used to +compress and expand the dynamic range of a signal. For instance +consider a logarithm quantized by a linear partitioning. Such a +partitioning is very poor for this large dynamic range. @code{compand} +can then be used to compress the signal prior to quantization, with +the signal being expanded afterwards. For example + +@example +octave:1> mu = 1.95; +octave:2> x = [0.01:0.01:2]; +octave:3> y = log (x); +octave:4> V = max (abs (y)); +octave:5> [i, z, d] = quantiz (y, [-4.875:0.25:0.875], [-5:0.25:1]); +octave:6> c = compand (y, minmu, V, "mu/compressor"); +octave:7> [i2, c2] = quantiz (c, [-4.875:0.25:0.875], [-5:0.25:1]); +octave:8> z2 = compand (c2, minmu, max (abs (c2)), "mu/expander"); +octave:9> d2 = sumsq (y - z2) / length (y); +octave:10> [d, d2] +ans = + + 0.0053885 0.0029935 +@end example + +@noindent +which demonstrates that the use of @code{compand} can significantly +reduce the distortion due to the quantization of signals with a large +dynamic range. + +@node Block Coding, Convolutional Coding, Source Coding, Top +@chapter Block Coding + +The error-correcting codes available in this package are discussed here. +These codes work with blocks of data, with no relation between one block +and the next. These codes create codewords based on the messages to +transmit that contain redundant information that allow the recovery of +the original message in the presence of errors. + +@menu +* Data Formats:: +* Binary Block Codes:: +* BCH Codes:: +* Reed-Solomon Codes:: +@end menu + +@node Data Formats, Binary Block Codes, , Block Coding +@section Data Formats + +All of the codes described in this section are binary and share similar +data formats. The exception is the Reed-Solomon coder which has a +significantly longer codeword length in general and therefore uses a +different representation to efficiently pass data. The user should refer +to the section about the Reed-Solomon codes for the data format used for +Reed-Solomon codes. + +In general @var{k} bits of data are considered to represent a single +message symbol. These @var{k} bits are coded into @var{n} bits of +data representing the codeword. The data can therefore be grouped +in one of three manners, to emphasis this grouping into bits, messages +and codewords + +@table @asis +@item A binary vector +Each element of the vector is either one or zero. If the data represents +an uncoded message the vector length should be an integer number of @var{k} +in length. +@item A binary matrix +In this case the data is ones and zeros grouped into rows, with each +representing a single message or codeword. The number of columns in the +matrix should be equal to @var{k} in the case of a uncoded message or +@var{n} in the case of a coded message. +@item A non-binary vector +In this case each element of the vector represents a message or codeword +in an integer format. The bits of the message or codeword are represented +by the bits of the vector elements with the least-significant bit +representing the first element in the message or codeword. +@end table + +An example demonstrating the relationship between the three data +formats can be seen below. + +@example +octave:1> k = 4; +octave:2> bin_vec = randint (k*10, 1); # Binary vector format +octave:3> bin_mat = reshape (bin_vec, k, 10)'; # Binary matrix format +octave:4> dec_vec = bi2de (bin_mat); # Decimal vector format +@end example + +The functions within this package will return data in the same format +to which it is given. It should be noted that internally the binary +matrix format is used, and thus if the message or codeword length is +large it is preferable to use the binary format to avoid internal +rounding errors. + +@node Binary Block Codes, BCH Codes, Data Formats, Block Coding +@section Binary Block Codes + +All of the codes presented here can be characterized by their + +@table @asis +@item Generator Matrix +A @var{k}-by-@var{n} matrix @var{G} to generate the codewords @var{C} from +the messages @var{T} by the matrix multiplication +@tex +$ {\bf C} = {\bf T} {\bf G}$. +@end tex +@ifnottex +@var{C} = @var{T} * @var{G}. +@end ifnottex +@item Parity Check Matrix +A '@var{n}-@var{k}'-by-@var{n} matrix @var{H} to check the parity of the +received symbols. If +@tex +$ {\bf H} {\bf R} = {\bf S} \ne 0$, +@end tex +@ifnottex +@var{H} * @var{R} = @var{S} != 0, +@end ifnottex +then an error has been detected. @var{S} can be used with the syndrome +table to correct this error +@item Syndrome Table +A 2^@var{k}-by-@var{n} matrix @var{ST} with the relationship of the error +vectors to the non-zero parities of the received symbols. That is, if +the received symbol is represented as +@tex +$ {\bf R} = ( {\bf T} + {\bf E} )\ mod\ 2$, +@end tex +@ifnottex +@var{R} = mod (@var{T} + @var{E}, 2), +@end ifnottex +then the error vector @var{E} is +@tex +${\bf ST}({\bf S})$. +@end tex +@ifnottex +@var{ST}(@var{S}). +@end ifnottex +@end table + +It is assumed for most of the functions in this package that the generator +matrix will be in a 'standard' form. That is the generator matrix can be +represented by + +@tex +$$ +{\bf G} = +\left[\matrix{g_{11} & g_{12} & \ldots & g_{1k} & 1 & 0 & \ldots & 0 \cr + g_{21} & g_{22} & & g_{2k} & 0 & 1 & & 0 \cr + \vdots & & & \vdots & \vdots& & & \vdots \cr + g_{k1} & g_{k2} & \ldots & g_{kk} & 0 & 0 & \ldots & 1}\right] +$$ +@end tex +@ifnottex +@example +@group + g(1,1) g(1,2) ... g(1,k) 1 0 ... 0 + g(2,1) g(2,2) g(2,k) 0 1 ... 0 + . . . . + . . . . + . . . . + g(k,1) g(k,2) ... g(k,k) 0 0 ... 1 +@end group +@end example +@end ifnottex + +@noindent +or + +@tex +$$ +{\bf G} = +\left[\matrix{1 & 0 & \ldots & 0 & g_{11} & g_{12} & \ldots & g_{1k} \cr + 0 & 1 & & 0 & g_{21} & g_{22} & & g_{2k} \cr + \vdots & & & \vdots & \vdots & & & \vdots \cr + 0 & 0 & \ldots & 1 & g_{k1} & g_{k2} & \ldots & g_{kk}}\right] +$$ +@end tex +@ifnottex +@example +@group + 1 0 ... 0 g(1,1) g(1,2) ... g(1,k) + 0 1 ... 0 g(2,1) g(2,2) g(2,k) + . . . . + . . . . + . . . . + 0 0 ... 1 g(k,1) g(k,2) ... g(k,k) +@end group +@end example +@end ifnottex + +@noindent +and similarly the parity check matrix can be represented by a combination +of an identity matrix and a square matrix. + +Some of the codes can also have their representation in terms of a +generator polynomial that can be used to create the generator and parity +check matrices. In the case of BCH codes, this generator polynomial is +used directly in the encoding and decoding without ever explicitly forming +the generator or parity check matrix. + +The user can create their own generator and parity check matrices, or +they can rely on the functions @code{hammgen}, @code{cyclgen} and +@code{cyclpoly}. The function @code{hammgen} creates parity check and +generator matrices for Hamming codes, while @code{cyclpoly} and +@code{cyclgen} create generator polynomials and matrices for generic +cyclic codes. An example of their use is + +@example +octave:1> m = 3; +octave:2> n = 2^m - 1; +octave:2> k = 4; +octave:3> [par, gen] = hammgen (m); +octave:4> [par2, gen2] = cyclgen (n, cyclpoly (n, k)); +@end example + +@noindent +which create identical parity check and generator matrices for the +[7,4] Hamming code. + +The syndrome table of the codes can be created with the function +@code{syndtable}, in the following manner + +@example +octave:1> [par, gen] = hammgen (3); +octave:2> st = syndtable (par); +@end example + +There exists two auxiliary functions @code{gen2par} and @code{gfweight}, +that convert between generator and parity check matrices and calculate +the Hamming distance of the codes. For instance + +@example +octave:1> par = hammgen (3); +octave:2> gen = gen2par (par); +octave:3> gfweight (gen) +ans = 3 +@end example + +It should be noted that for large values of @var{n}, the generator, +parity check and syndrome table matrices are very large. There is +therefore an internal limitation on the size of the block codes that +can be created that limits the codeword length @var{n} to less than 64. +This is still excessively large for the syndrome table, so use caution +with these codes. These limitations do not apply to the Reed-Solomon +or BCH codes. + +The top-level encode and decode functions are @code{encode} and +@code{decode}, which can be used with all codes, except the Reed-Solomon +code. The basic call to both of these functions passes the message +to code/decode, the codeword length, the message length and the type +of coding to use. There are four basic types that are available with +these functions + +@table @asis +@item "linear" +Generic linear block codes +@item "cyclic" +Cyclic linear block codes +@item "hamming" +Hamming codes +@item "bch" +Bose Chaudhuri Hocquenghem (BCH) block codes +@end table + +It is not possible to distinguish between a binary vector and a decimal +vector coding of the messages that just happens to only have ones and +zeros. Therefore the functions @code{encode} and @code{decode} must be +told the format of the messages in the following manner. + +@example +octave:1> m = 3; +octave:2> n = 7; +octave:3> k = 4; +octave:4> msg_bin = randint (10, k); +octave:5> cbin = encode (msg_bin, n, k, "hamming/binary"); +octave:5> cdec = encode (bi2de (msg), n, k, "hamming/decimal"); +@end example + +@noindent +which codes a binary matrix and a non-binary vector representation of a +message, returning the coded message in the same format. The functions +@code{encode} and @code{decode} by default accept binary coded +messages. Therefore "hamming" is equivalent to "hamming/binary". + +Except for the BCH codes, the function @code{encode} and @code{decode} +internally create the generator, parity check and syndrome table +matrices. Therefore if repeated calls to @code{encode} and @code{decode} +are made, it will often be faster to create these matrices externally +and pass them as an argument. For example + +@example +n = 15; +k = 11; +[par, gen] = hammgen (4); +code1 = code2 = zeros (100, 15) +for i = 1:100 + msg = get_msg (i); + code1(i,:) = encode (msg, n, k, "linear", gen); # This is faster + code2(i,:) = encode (msg, n, k, "hamming"); # than this !!! +endfor +@end example + +In the case of the BCH codes the low-level functions described in the +next section are used directly by the @code{encode} and @code{decode} +functions. + + +@node BCH Codes, Reed-Solomon Codes, Binary Block Codes, Block Coding +@section BCH Codes + +The BCH coder used here is based on code written by Robert Morelos-Zaragoza +(r.morelos-zaragoza@@ieee.org). This code was originally written in C +and has been converted for use as an Octave oct-file. + +@iftex +Called without arguments, @code{bchpoly} returns a table of valid BCH +error correcting codes and their error-correction capability +as seen in Table 1. + +@center Table 2: Table of valid BCH codes with codeword length less than 511. + +@multitable @columnfractions .083 .083 .083 .083 .083 .083 .083 .083 .083 .083 .083 .083 +@item N @tab K @tab T @tab N @tab K @tab T @tab N @tab K @tab T @tab N @tab K @tab T +@item 7 @tab 4 @tab 1 @tab 127 @tab 36 @tab 15 @tab 255 @tab 45 @tab 43 @tab 511 @tab 268 @tab 29 +@item 15 @tab 11 @tab 1 @tab 127 @tab 29 @tab 21 @tab 255 @tab 37 @tab 45 @tab 511 @tab 259 @tab 30 +@item 15 @tab 7 @tab 2 @tab 127 @tab 22 @tab 23 @tab 255 @tab 29 @tab 47 @tab 511 @tab 250 @tab 31 +@item 15 @tab 5 @tab 3 @tab 127 @tab 15 @tab 27 @tab 255 @tab 21 @tab 55 @tab 511 @tab 241 @tab 36 +@item 31 @tab 26 @tab 1 @tab 127 @tab 8 @tab 31 @tab 255 @tab 13 @tab 59 @tab 511 @tab 238 @tab 37 +@item 31 @tab 21 @tab 2 @tab 255 @tab 247 @tab 1 @tab 255 @tab 9 @tab 63 @tab 511 @tab 229 @tab 38 +@item 31 @tab 16 @tab 3 @tab 255 @tab 239 @tab 2 @tab 511 @tab 502 @tab 1 @tab 511 @tab 220 @tab 39 +@item 31 @tab 11 @tab 5 @tab 255 @tab 231 @tab 3 @tab 511 @tab 493 @tab 2 @tab 511 @tab 211 @tab 41 +@item 31 @tab 6 @tab 7 @tab 255 @tab 223 @tab 4 @tab 511 @tab 484 @tab 3 @tab 511 @tab 202 @tab 42 +@item 63 @tab 57 @tab 1 @tab 255 @tab 215 @tab 5 @tab 511 @tab 475 @tab 4 @tab 511 @tab 193 @tab 43 +@item 63 @tab 51 @tab 2 @tab 255 @tab 207 @tab 6 @tab 511 @tab 466 @tab 5 @tab 511 @tab 184 @tab 45 +@item 63 @tab 45 @tab 3 @tab 255 @tab 199 @tab 7 @tab 511 @tab 457 @tab 6 @tab 511 @tab 175 @tab 46 +@item 63 @tab 39 @tab 4 @tab 255 @tab 191 @tab 8 @tab 511 @tab 448 @tab 7 @tab 511 @tab 166 @tab 47 +@item 63 @tab 36 @tab 5 @tab 255 @tab 187 @tab 9 @tab 511 @tab 439 @tab 8 @tab 511 @tab 157 @tab 51 +@item 63 @tab 30 @tab 6 @tab 255 @tab 179 @tab 10 @tab 511 @tab 430 @tab 9 @tab 511 @tab 148 @tab 53 +@item 63 @tab 24 @tab 7 @tab 255 @tab 171 @tab 11 @tab 511 @tab 421 @tab 10 @tab 511 @tab 139 @tab 54 +@item 63 @tab 18 @tab 10 @tab 255 @tab 163 @tab 12 @tab 511 @tab 412 @tab 11 @tab 511 @tab 130 @tab 55 +@item 63 @tab 16 @tab 11 @tab 255 @tab 155 @tab 13 @tab 511 @tab 403 @tab 12 @tab 511 @tab 121 @tab 58 +@item 63 @tab 10 @tab 13 @tab 255 @tab 147 @tab 14 @tab 511 @tab 394 @tab 13 @tab 511 @tab 112 @tab 59 +@item 63 @tab 7 @tab 15 @tab 255 @tab 139 @tab 15 @tab 511 @tab 385 @tab 14 @tab 511 @tab 103 @tab 61 +@item 127 @tab 120 @tab 1 @tab 255 @tab 131 @tab 18 @tab 511 @tab 376 @tab 15 @tab 511 @tab 94 @tab 62 +@item 127 @tab 113 @tab 2 @tab 255 @tab 123 @tab 19 @tab 511 @tab 367 @tab 17 @tab 511 @tab 85 @tab 63 +@item 127 @tab 106 @tab 3 @tab 255 @tab 115 @tab 21 @tab 511 @tab 358 @tab 18 @tab 511 @tab 76 @tab 85 +@item 127 @tab 99 @tab 4 @tab 255 @tab 107 @tab 22 @tab 511 @tab 349 @tab 19 @tab 511 @tab 67 @tab 87 +@item 127 @tab 92 @tab 5 @tab 255 @tab 99 @tab 23 @tab 511 @tab 340 @tab 20 @tab 511 @tab 58 @tab 91 +@item 127 @tab 85 @tab 6 @tab 255 @tab 91 @tab 25 @tab 511 @tab 331 @tab 21 @tab 511 @tab 49 @tab 93 +@item 127 @tab 78 @tab 7 @tab 255 @tab 87 @tab 26 @tab 511 @tab 322 @tab 22 @tab 511 @tab 40 @tab 95 +@item 127 @tab 71 @tab 9 @tab 255 @tab 79 @tab 27 @tab 511 @tab 313 @tab 23 @tab 511 @tab 31 @tab 109 +@item 127 @tab 64 @tab 10 @tab 255 @tab 71 @tab 29 @tab 511 @tab 304 @tab 25 @tab 511 @tab 28 @tab 111 +@item 127 @tab 57 @tab 11 @tab 255 @tab 63 @tab 30 @tab 511 @tab 295 @tab 26 @tab 511 @tab 19 @tab 119 +@item 127 @tab 50 @tab 13 @tab 255 @tab 55 @tab 31 @tab 511 @tab 286 @tab 27 @tab 511 @tab 10 @tab 127 +@item 127 @tab 43 @tab 14 @tab 255 @tab 47 @tab 42 @tab 511 @tab 277 @tab 28 @tab @tab @tab +@end multitable + +@end iftex +@ifnottex +Called without arguments, @code{bchpoly} returns a table of valid BCH +error correcting codes and their error-correction capability. +@end ifnottex +The first returned column of @code{bchpoly} is the codeword length, +the second the message length and the third the error correction capability +of the code. Called with one argument, @code{bchpoly} returns similar +output, but only for the specified codeword length. In this manner codes +with codeword length greater than 511 can be found. + +In general the codeword length is of the form @code{2^@var{m} - 1}, where +@var{m} is an integer. However if [@var{n},@var{k}] is a valid BCH +code, then it is also possible to use a shortened BCH form of the form +@code{[@var{n}-@var{x},@var{k}-@var{x}]}. + +With two or more arguments, @code{bchpoly} is used to find the generator +polynomial of a valid BCH code. For instance + +@example +octave:1> bchpoly (15, 7) +ans = + + 1 0 0 0 1 0 1 1 1 + +octave:2> bchpoly (14, 6) +ans = + + 1 0 0 0 1 0 1 1 1 +@end example + +@noindent +show that the generator polynomial of a [15,7] BCH code with the default +primitive polynomial is + +@tex +$$ 1 + x^4 + x^6 + x^7 + x^8 $$ +@end tex +@ifnottex +1 + @var{x} ^ 4 + @var{x} ^ 6 + @var{x} ^ 7 + @var{x} ^ 8 +@end ifnottex + +Using a different primitive polynomial to define the Galois Field over +which the BCH code is defined results in a different generator polynomial +as can be seen in the example. + +@example +octave:1> bchpoly ([1 1 0 0 1], 7) +ans = + + 1 0 0 0 1 0 1 1 1 + +octave:2> bchpoly ([1 0 0 1 1], 7) +ans = + + 1 1 1 0 1 0 0 0 1 +@end example + +It is recommend not to convert the generator polynomials created by +@code{bchpoly} into generator and parity check matrices with the +BCH codes, as the underlying BCH software is faster than the generic +coding software and can treat significantly longer codes. + +As well as using the @code{encode} and @code{decode} functions previously +discussed, the user can directly use the low-level BCH functions +@code{bchenco} and @code{bchdeco}. In this case the messages must be +in the format of a binary matrix with @var{k} columns + +@example +octave:1> n = 31; +octave:2> pgs = bchpoly (n); +octave:3> pg = pgs(floor (rand () * (rows (pgs) + 1)),:); # Pick a poly +octave:4> k = pg(2); +octave:5> t = pg(3); +octave:6> msg = randint (10, k); +octave:7> code = bchenco (msg, n, k); +octave:8> noisy = code + [ones(10, 1), zeros(10, n-1)]; +octave:9> dec = bchdeco (code, k, t); +@end example + +@node Reed-Solomon Codes, , BCH Codes, Block Coding +@section Reed-Solomon Codes + +@menu +* Representation of Reed-Solomon Messages:: +* Creating and Decoding Messages:: +* Shortened Reed-Solomon Codes:: +@end menu + +@node Representation of Reed-Solomon Messages, Creating and Decoding Messages, , Reed-Solomon Codes +@subsection Representation of Reed-Solomon Messages + +The Reed-Solomon coder used in this package is based on code written by +Phil Karn (http://www.ka9q.net/code/fec). This code was originally written +in C and has been converted for use as an Octave oct-file. + +Reed-Solomon codes are based on Galois Fields of even characteristics +GF(2^M). Many of the properties of Galois Fields are therefore important +when considering Reed-Solomon coders. + +The representation of the symbols of the Reed-Solomon code differs from +the other block codes, in that the other block codes use a binary +representation, while the Reed-Solomon code represents each m-bit symbol +by an integer. The elements of the message and codeword must be elements +of the Galois Field corresponding to the Reed-Solomon code. Thus to +code a message with a [7,5] Reed-Solomon code an example is + +@example +octave:1> m = 3; +octave:2> n = 7; +octave:3> k = 5; +octave:4> msg = gf (floor (2^m * rand (2, k)), m) +msg = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 5 0 6 3 2 + 4 1 3 1 2 + +octave:5> code = rsenc (msg, n, k) +code = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 5 0 6 3 2 3 5 + 4 1 3 1 2 6 3 +@end example + +The variable @var{n} is the codeword length of the Reed-Solomon coder, +while @var{k} is the message length. It should be noted that @var{k} +should be less than @var{n} and that @code{@var{n} - @var{k}} should be +even. The error correcting capability of the Reed-Solomon code is then +@code{(@var{n} - @var{k})/2} symbols. @var{m} is the number of bits per +symbol, and is related to @var{n} by @code{@var{n} = 2^@var{m} - 1}. +For a valid Reed-Solomon coder, @var{m} should be between 3 and 16. + +@node Creating and Decoding Messages, Shortened Reed-Solomon Codes, Representation of Reed-Solomon Messages, Reed-Solomon Codes +@subsection Creating and Decoding Messages + +The Reed-Solomon encoding function requires at least three arguments. The +first @var{msg} is the message in encodes, the second is @var{n} the codeword +length and @var{k} is the message length. Therefore @var{msg} must have +@var{k} columns and the output will have @var{n} columns of symbols. + +The message itself is many up of elements of a Galois Field +GF(2^M). Normally, The order of the Galois Field (M), is related to the +codeword length by @code{@var{n} = 2^@var{m} - 1}. Another important +parameter when determining the behavior of the Reed-Solomon coder is +the primitive polynomial of the Galois Field (see @code{gf}). Thus +the messages + +@example +octave:1> msg0 = gf ([0, 1, 2, 3], 3); +octave:2> msg1 = gf ([0, 1, 2, 3], 3, 13); +@end example + +@noindent +will not result in the same Reed-Solomon coding. Finally, the parity of +the Reed-Solomon code are generated with the use of a generator +polynomial. The parity symbols are then generated by treating the message +to encode as a polynomial and finding the remainder of the division of +this polynomial by the generator polynomial. Therefore the generator +polynomial must have as many roots as @code{@var{n} - @var{k}}. Whether +the parity symbols are placed before or afterwards the message will then +determine which end of the message is the most-significant term of the +polynomial representing the message. The parity symbols are therefore +different in these two cases. The position of the parity symbols can be +chosen by specifying "beginning" or "end" to @code{rsenc} and @code{rsdec}. +By default the parity symbols are placed after the message. + +Valid generator polynomials can be constructed with the @code{rsgenpoly} +function. The roots of the generator polynomial are then defined by + +@tex +$$ +g = (x - A^{bs}) (x - A^{(b+1)s}) \cdots (x - A ^{(b+2t-1)s}). +$$ +@end tex +@ifnottex + +@example +@var{g} = (@var{x} - A^(@var{b}*@var{s})) * (@var{x} - A^((@var{b}+1)*@var{s})) * @dots{} * (@var{x} - A^((@var{b}+2*@var{t}-1)*@var{s})). +@end example +@end ifnottex + +@noindent +where @var{t} is @code{(@var{n} - @var{k})/2}, A is the primitive element +of the Galois Field, @var{b} is the first consecutive root, and @var{s} +is the step between roots. Generator polynomial of this form are constructed +by @code{rsgenpoly} and can be passed to both @code{rsenc} and @code{rsdec}. +It is also possible to pass the @var{b} and @var{s} values directly to +@code{rsenc} and @code{rsdec}. In the case of @code{rsdec} passing @var{b} +and @var{s} can make the decoding faster. + +Consider the example below. + +@example +octave:1> m = 8; +octave:2> n = 2^m - 1; +octave:3> k = 223; +octave:4> prim = 391; +octave:5> b = 112; +octave:6> s = 11; +octave:7> gg = rsgenpoly (n, k, prim, b, s); +octave:8> msg = gf (floor (2^m * rand (17, k)), m, prim); +octave:9> code = rsenc (msg, n, k, gg); +octave:10> noisy = code + [toeplitz([ones(1,17)], zeros(1,17)), zeros(17,238)]; +octave:11> [dec, nerr] = rsdec (msg, n, k, b, s); +octave:12> nerr' +ans = + + 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 -1 + +octave:13> any (msg' != dec') +ans = + + 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 +@end example + +This is an interesting example in that it demonstrates many of the +additional arguments of the Reed-Solomon functions. In particular +this example approximates the CCSDS standard Reed-Solomon coder, +lacking only the dual-basis lookup tables used in this standard. +The CCSDS uses non-default values to all of the basic functions +involved in the Reed-Solomon encoding, since it has a non-default +primitive polynomial, generator polynomial, etc. + +The example creates 17 message blocks and adds between 1 and 17 error +symbols to these block. As can be seen @var{nerr} gives the number of +errors corrected. In the case of 17 introduced errors @var{nerr} +equals -1, indicating a decoding failure. This is normal as the +correction ability of this code is up to 16 error symbols. Comparing +the input message and the decoding it can be seen that as expected, +only the case of 17 errors has not been correctly decoded. + +@node Shortened Reed-Solomon Codes, , Creating and Decoding Messages, Reed-Solomon Codes +@subsection Shortened Reed-Solomon Codes + +In general the codeword length of the Reed-Solomon coder is chosen so +that it is related directly to the order of the Galois Field by the +formula @code{@var{n} = 2^@var{m} - 1}. Although, the underlying +Reed-Solomon coding must operate over valid codeword length, there +are sometimes reasons to assume that the codeword length will be shorter. +In this case the message is padded with zeros before coding, and the +zeros are stripped from the returned block. For example consider the +shortened [6,4] Reed-Solomon below + +@example +octave:1> m = 3; +octave:2> n = 6; +octave:3> k = 4; +octave:4> msg = gf (floor (2^m * rand (2, k)), m) +msg = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 7 0 2 5 + 1 5 7 1 + +octave:5> code = rsenc (msg, n, k) +code = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 7 0 2 5 2 3 + 1 5 7 1 0 2 +@end example + + +@node Convolutional Coding, Modulations, Block Coding, Top +@chapter Convolutional Coding + +Some initial support for convolutional codes is provided by the +functions described in this chapter. Convolutional codes are different +from block codes in that the sequence of preceding symbols is taken +into account when computing the output symbol of the coder. + +@menu +* Trellis Structure:: +* Convolutional Encoding:: +@end menu + +@node Trellis Structure, Convolutional Encoding, , Convolutional Coding +@section Trellis Structure + +Like block codes, convolutional codes can be described by a set of +generator polynomials. Each polynomial describes the combination of +current and previous input symbols used to compute one output bit of +the encoder. + +The state transitions and outputs of a convolutional encoder can also be +described by a trellis diagram. This diagram describes the transitions +between states and the outputs of the encoder as a function of the +current state and the current input symbol. A trellis structure can be +created from a set of generator polynomials, specified as octal numbers +by convention, + +@example +octave:1> g0 = 13; +octave:2> g1 = 17; +octave:3> trellis = poly2trellis (4, [g0, g1]); +@end example + +@noindent +where @var{g0} and @var{g1} are the two polynomials of a rate 1/2 +encoder with a constraint length of 4. The returned trellis structure +contains the following fields + +@table @samp +@item numInputSymbols +The number of possible input symbols in the input sequence. +@item numOutputSymbols +The number of possible output symbols in the encoded sequence. +@item numStates +The number of possible states that the encoder can take. +@item nextStates +The state transition table for the encoder. Each row contains the +(zero-based) indices of the states reachable from the state represented +by that row for each possible input symbol. +@item outputs +The output table for the encoder. Each row contains the (octal-encoded) +output symbols produced by the encoder in the state represented by that +row for each possible input symbol. +@end table + +To check if a variable references a structure that is a valid trellis +describing a convolutional encoder, use the @code{istrellis} function. + +@node Convolutional Encoding, , Trellis Structure, Convolutional Coding +@section Convolutional Encoding + +The convolutional encoding function takes the message to be encoded and +a trellis describing the encoder. The message must be a binary vector +containing an even number of symbols. For example, using the encoder +from the previous section, + +@example +octave:1> trellis = poly2trellis (4, [13, 17]); +octave:2> msg = [1 1 0 1 1 0 0 0]; +octave:3> out = convenc (msg, trellis) +out = + + 1 1 1 0 1 0 1 1 0 1 1 0 0 0 1 1 +@end example + +The initial state of the encoder can also be passed in to @code{convenc}, +and the ending state can be read with an optional output argument. +Encoding a different vector with a different initial state using the +same encoder, + +@example +octave:4> msg = [0 1 1 0 1 0 1 1]; +octave:5> [out, state] = convenc (msg, trellis, [], 4) +out = + + 0 1 0 0 0 1 1 0 1 1 1 0 0 0 0 1 + +state = 6 +@end example + +@noindent +returns both the encoded array and the final state of the convolutional +encoder. This can be used to encode data in blocks, for example, saving +and restoring the internal state of the encoder for each subsequent +input block. + +@node Modulations, Special Filters, Convolutional Coding, Top +@chapter Modulations + +To be written. + +Currently have functions amodce, ademodce, apkconst, demodmap, modmap, +qaskdeco, qaskenco, genqammod, pamdemod, pammod, pskdemod and pskmod. + +@node Special Filters, Galois Fields, Modulations, Top +@chapter Special Filters + +To be written. + +@node Galois Fields, Function Reference, Special Filters, Top +@chapter Galois Fields + +@menu +* Galois Field Basics:: +* Manipulating Galois Fields:: +@end menu + +@node Galois Field Basics, Manipulating Galois Fields, , Galois Fields +@section Galois Field Basics + +A Galois Field is a finite algebraic field. This package implements a +Galois Field type in Octave having 2^M members where M is an integer +between 1 and 16. Such fields are denoted as GF(2^M) and are used in +error correcting codes in communications systems. Galois Fields having +odd numbers of elements are not implemented. + +The @emph{primitive element} of a Galois Field has the property that all +elements of the Galois Field can be represented as a power of this element. +The @emph{primitive polynomial} is the minimum polynomial of some primitive +element in GF(2^M) and is irreducible and of order M. This means that the +primitive element is a root of the primitive polynomial. + +The elements of the Galois Field GF(2^M) are represented as the values +0 to 2^M -1 by Octave. The first two elements represent the zero and unity +values of the Galois Field and are unique in all fields. The element +represented by 2 is the primitive element of the field and all elements can +be represented as combinations of the primitive element and unity as follows + +@multitable @columnfractions .33 .33 .33 +@item Integer @tab Binary @tab Element of GF(2^M) +@item 0 @tab 000 @tab @code{0} +@item 1 @tab 001 @tab @code{1} +@item 2 @tab 010 @tab @code{A} +@item 3 @tab 011 @tab @code{A + 1} +@item 4 @tab 100 @tab @code{A^2} +@item 5 @tab 101 @tab @code{A^2 + 1} +@item 6 @tab 110 @tab @code{A^2 + A} +@item 7 @tab 111 @tab @code{A^2 + A + 1} +@end multitable + +It should be noted that there is often more than a single primitive +polynomial of GF(2^M). Each Galois Field over a different primitive +polynomial represents a different realization of the Field. The +representations above however rest valid. + +@menu +* Creating Galois Fields:: +* Primitive Polynomials:: +* Accessing Internal Fields:: +* Function Overloading:: +* Known Problems:: +@end menu + +@node Creating Galois Fields, Primitive Polynomials, , Galois Field Basics +@subsection Creating Galois Fields + +To work with a Galois Field GF(2^M) in Octave, you must first create a variable +that Octave recognizes as a Galois Field. This is done with the function +@code{gf (@var{a}, @var{m})} as follows. + +@example +octave:1> a = [0:7]; +octave:2> b = gf (a, 4) +b = +GF(2^4) array. Primitive Polynomial = D^4+D+1 (decimal 19) + +Array elements = + + 0 1 2 3 4 5 6 7 +@end example + +This creates an array @var{b} with 8 elements that Octave recognizes as a +Galois Field. The field is created with the default primitive polynomial for +the field GF(2^4). It can be verified that a variable is in fact a Galois +Field with the functions @code{isgalois} or @code{whos}. + +@example +octave:3> isgalois (a) +ans = 0 +octave:4> isgalois (b) +ans = 1 +octave:5> whos +Variables in the current scope: + + Attr Name Size Bytes Class + ==== ==== ==== ===== ===== + a 1x8 24 double + b 1x8 32 galois + +Total is 16 elements using 56 bytes +@end example + +It is also possible to create a Galois Field with an arbitrary primitive +polynomial. However, if the polynomial is not a primitive polynomial of +the field, and error message is returned. For instance. + +@example +octave:1> a = [0:7]; +octave:2> b = gf (a, 4, 25) +b = +GF(2^4) array. Primitive Polynomial = D^4+D^3+1 (decimal 25) + +Array elements = + + 0 1 2 3 4 5 6 7 + +octave:3> c = gf (a, 4, 21) +error: gf: primitive polynomial (21) of Galois Field must be irreducible +@end example + +The function @code{gftable} is included for compatibility with @sc{matlab}. In +@sc{matlab} this function is used to create the lookup tables used to accelerate +the computations over the Galois Field and store them to a file. However +Octave stores these parameters for all of the fields currently in use and +so this function is not required, although it is silently accepted. + +@node Primitive Polynomials, Accessing Internal Fields, Creating Galois Fields, Galois Field Basics +@subsection Primitive Polynomials + +The function @code{gf (@var{a}, @var{m})} creates a Galois Field using the default primitive +polynomial. However there exists many possible primitive polynomials for most +Galois Fields. Two functions exist for identifying primitive polynomials, +@code{isprimitive} and @code{primpoly}. @code{primpoly (@var{m}, @var{opt})} is +used to identify the primitive polynomials of the fields GF(2^M). For example + +@example +octave:1> primpoly (4) + +Primitive polynomial(s) = + +D^4+D+1 + +ans = 19 +@end example + +@noindent +identifies the default primitive polynomials of the field GF(2^M), which +is the same as @code{primpoly (4, "min")}. All of the primitive polynomials +of a field can be identified with the function @code{primpoly (@var{m}, "all")}. +For example + +@example +octave:1> primpoly (4, "all") + +Primitive polynomial(s) = + +D^4+D+1 +D^4+D^3+1 + +ans = + + 19 25 +@end example + +@noindent +while @code{primpoly (@var{m}, "max")} returns the maximum primitive polynomial +of the field, which for the case above is 25. The function @code{primpoly} +can also be used to identify the primitive polynomials having only a +certain number of non-zero terms. For instance + +@example +octave:1> primpoly (5, 3) + +Primitive polynomial(s) = + +D^5+D^2+1 +D^5+D^3+1 + +ans = + + 37 41 +@end example + +@noindent +identifies the polynomials with only three terms that can be used as +primitive polynomials of GF(2^5). If no primitive polynomials existing +having the requested number of terms then @code{primpoly} returns an +empty vector. That is + +@example +octave:1> primpoly (5, 2) +warning: primpoly: No primitive polynomial satisfies the given constraints + +ans = [](1x0) +@end example + +As can be seen above, @code{primpoly} displays the polynomial forms the +the polynomials that it finds. This output can be suppressed with the +"nodisplay" option, while the returned value is left unchanged. + +@example +octave:1> primpoly (4, "all", "nodisplay") +ans = + + 19 25 +@end example + +@code{isprimitive (@var{a})} identifies whether the elements of @var{a} can +be used as primitive polynomials of the Galois Fields GF(2^M). Consider +as an example the fields GF(2^4). The primitive polynomials of these fields +must have an order m and so their integer representation must be between +16 and 31. Therefore @code{isprimitive} can be used in a similar manner to +@code{primpoly} as follows + +@example +octave:1> find (isprimitive (16:31)) + 15 +ans = + + 19 25 +@end example + +@noindent +which finds all of the primitive polynomials of GF(2^4). + +@node Accessing Internal Fields, Function Overloading, Primitive Polynomials, Galois Field Basics +@subsection Accessing Internal Fields + +Once a variable has been defined as a Galois Field, the parameters of the +field of this structure can be obtained by adding a suffix to the variable. +Valid suffixes are '.m', '.prim_poly' and '.x', which return the order of the +Galois Field, its primitive polynomial and the data the variable contains +respectively. For instance + +@example +octave:1> a = [0:7]; +octave:2> b = gf (a, 4); +octave:3> b.m +ans = 4 +octave:4> b.prim_poly +ans = 19 +octave:5> c = b.x; +octave:6> whos +Variables in the current scope: + + Attr Name Size Bytes Class + ==== ==== ==== ===== ===== + a 1x8 24 double + b 1x8 32 galois + c 1x8 64 double + +Total is 24 elements using 120 bytes +@end example + +@c Note that if code compiled with GALOIS_DISP_PRIVATES then '.n', '.alpha_to' +@c and '.index_of' are also available. These give 2^m-1, the lookup table +@c and its inverse respectively. + +Please note that it is explicitly forbidden to modify the Galois field by +accessing these variables. For instance + +@example +octave:1> a = gf ([0:7], 3); +octave:2> a.prim_poly = 13; +@end example + +@noindent +is explicitly forbidden. The result of this will be to replace the +Galois array @var{a} with a structure @var{a} with a single element +called '.prim_poly'. To modify the order or primitive polynomial of a +field, a new field must be created and the data copied. That is + +@example +octave:1> a = gf ([0:7], 3); +octave:2> a = gf (a.x, a.m, 13); +@end example + +@node Function Overloading, Known Problems, Accessing Internal Fields, Galois Field Basics +@subsection Function Overloading + +An important consideration in the use of the Galois Field package is +that many of the internal functions of Octave, such as @code{roots}, can +not accept Galois Fields as an input. This package therefore uses Octave +classes to @emph{overload} the internal Octave functions with equivalent +functions that work with Galois Fields, so that the standard function names +can be used. + +The version of the function that is chosen is determined by the first +argument of the function. This is a temporary situation until the +Galois Field class constructor can be rewritten to allow the use of the +@code{superiorto} function to define the galois class with a higher +precedence. So, considering the @code{filter} function, +if the first argument is a @emph{Matrix}, then the normal version of +the function is called regardless of whether the other arguments of the +function are Galois vectors or not. + +Other Octave functions work correctly with Galois Fields and so overloaded +versions are not necessary. This include such functions as @code{size} and +@code{polyval}. + +It is also useful to use the '.x' option discussed in the previous section, +to extract the raw data of the Galois field for use with some functions. An +example is + +@example +octave:1> a = minpol (gf (14, 5)); +octave:2> b = de2bi (a.x, [], "left-msb"); +@end example + +@noindent +converts the polynomial form of the minimum polynomial of 14 in GF(2^5) into +an integer. Finally help for the Galois specific versions of the functions +must explicitly call the correct function as + +@example +octave:1> help @@galois/conv +@end example + +@node Known Problems, , Function Overloading, Galois Field Basics +@subsection Known Problems + +Please review the following list of known problems with the Galois type +before reporting a bug against this package. + +@table @asis +@item Saving and loading Galois variables + +Saving a Galois variable to a file is as simple as + +@example +octave:1> a = gf (@dots{}); +octave:2> save a.mat a +@end example + +@noindent +where @var{a} is any Galois variable. Galois variables can be saved in the +Octave binary and ASCII formats, as well as the HDF5 format. To load a +Galois variable from a file, the Galois type must already be registered to +the Octave interpreter prior to the call to @code{load}. If no Galois +variables have been created yet, you will have to do something like + +@example +octave:1> dummy = gf (1); +octave:2> load a.mat +@end example + +@item Logarithm of zero does not return NaN +The logarithm of zero in a Galois field is not defined. However, to avoid +segmentation faults in later calculations the logarithm of zero is defined +as @code{2^@var{m} - 1}, whose value is not the logarithm of any other value +in the Galois field. A warning is also shown to tell the user about the +problem. For example + +@example +octave:1> m = 3; +octave:2> a = log (gf ([0:2^m-1], m)) +warning: log of zero undefined in Galois field +a = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 7 0 1 3 2 6 4 5 +@end example + +To fix this problem would require a major rewrite of all code, adding +an exception for the case of NaN to all basic operators. These +exceptions will certainly slow the code down. + +@item Speed +The code was written piecemeal with no attention to optimization. Some +operations may be slower than they could be. Contributions are welcome. + +@end table + +@node Manipulating Galois Fields, , Galois Field Basics, Galois Fields +@section Manipulating Galois Fields + +@menu +* Expressions manipulation and assignment:: +* Unary operations:: +* Arithmetic operations:: +* Comparison operations:: +* Polynomial manipulations:: +* Linear Algebra:: +* Signal Processing:: +@end menu + +@node Expressions manipulation and assignment, Unary operations, , Manipulating Galois Fields +@subsection Expressions, manipulation and assignment + +Galois variables can be treated in similar manner to other variables within +Octave. For instance Galois fields can be accessed using index expressions +in a similar manner to all other Octave matrices. For example + +@example +octave:1> a = gf ([[0:7]; [7:-1:0]], 3) +a = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 0 1 2 3 4 5 6 7 + 7 6 5 4 3 2 1 0 + +octave:2> b = a(1,:) +b = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 0 1 2 3 4 5 6 7 +@end example + +Galois arrays can equally use indexed assignments. That is, the data +in the array can be partially replaced, on the condition that the two +fields are identical. An example is + +@example +octave:1> a = gf (ones (2, 8), 3); +octave:2> b = gf (zeros (1, 8), 3); +octave:3> a(1,:) = b +a = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 0 0 0 0 0 0 0 0 + 1 1 1 1 1 1 1 1 +@end example + +Implicit conversions between normal matrices and Galois arrays are possible. +For instance data can be directly copied from a Galois array to a real matrix +as follows. + +@example +octave:1> a = gf (ones (2, 8), 3); +octave:2> b = zeros (2, 8); +octave:3> b(2,:) = a(2,:) +b = + + 0 0 0 0 0 0 0 0 + 1 1 1 1 1 1 1 1 +@end example + +The inverse is equally possible, with the proviso that the data in the matrix +is valid in the Galois field. For instance + +@example +octave:1> a = gf ([0:7], 3); +octave:2> a(1) = 1; +@end example + +@noindent +is valid, while + +@example +octave:1> a = gf ([0:7], 3); +octave:2> a(1) = 8; +@end example + +@noindent +is not, since 8 is not an element of GF(2^3). This is a basic rule of +manipulating Galois arrays. That is matrices and scalars can be used in +conjunction with a Galois array as long as they contain valid data +within the Galois field. In this case they will be assumed to be of the +same field. + +Galois arrays can also be concatenated with real matrices or with other +Galois arrays in the same field. For example + +@example +octave:1> a = [gf([0:7], 3); gf([7:-1:0], 3)]; +octave:2> b = [a, a]; +octave:3> c = [a, eye(2)]; +octave:3> whos +Variables in the current scope: + + Attr Name Size Bytes Class + ==== ==== ==== ===== ===== + a 2x8 64 galois + b 2x16 128 galois + c 2x10 80 galois + +Total is 68 elements using 272 bytes +@end example + +Other basic manipulations of Galois arrays are + +@table @code +@item isempty +Returns true if the Galois array is empty. + +@item size +Returns the number of rows and columns in the Galois array. + +@item length +Returns the length of a Galois vector, or the maximum of rows or columns +of Galois arrays. + +@item find +Find the indexes of the non-zero elements of a Galois array. + +@item diag +Create a diagonal Galois array from a Galois vector, or extract a diagonal +from a Galois array. + +@item reshape +Change the shape of the Galois array. + +@end table + +@node Unary operations, Arithmetic operations, Expressions manipulation and assignment, Manipulating Galois Fields +@subsection Unary operations + +The same unary operators that are available for normal Octave matrices are +also available for Galois arrays. These operations are + +@table @code +@item +@var{x} +Unary plus. This operator has no effect on the operand. + +@item -@var{x} +Unary minus. Note that in a Galois Field this operator also has no effect +on the operand. + +@item !@var{x} +Returns true for zero elements of Galois Array. + +@item @var{x}' +Complex conjugate transpose. As the Galois Field only contains integer +values, this is equivalent to the transpose operator. + +@item @var{x}.' +Transpose of the Galois array. +@end table + +@node Arithmetic operations, Comparison operations, Unary operations, Manipulating Galois Fields +@subsection Arithmetic operations + +The available arithmetic operations on Galois arrays are the same as on +other Octave matrices. It should be noted that both operands must be in +the same Galois Field. If one operand is a Galois array and the second is +a matrix or scalar, then the second operand is silently converted to the +same Galois Field. The element(s) of these matrix or scalar must however +be valid members of the Galois field. Thus + +@example +octave:1> a = gf ([0:7], 3); +octave:2> b = a + [0:7]; +@end example + +@noindent +is valid, while + +@example +octave:1> a = gf ([0:7], 3); +octave:2> b = a + [1:8]; +@end example + +@noindent +is not, since 8 is not a valid element of GF(2^3). The available arithmetic +operators are + +@table @code +@item @var{x} + @var{y} +Addition. If both operands are Galois arrays or matrices, the number of rows +and columns must both agree. If one operand is a is a Galois array with a +single element or a scalar, its value is added to all the elements of the +other operand. The @code{+} operator on a Galois Field is equivalent to an +exclusive-or on normal integers. + +@item @var{x} .+ @var{y} +Element by element addition. This operator is equivalent to @code{+}. + +@item @var{x} - @var{y} +As both @code{+} and @code{-} in a Galois Field are equivalent to an +exclusive-or for normal integers, @code{-} is equivalent to the @code{+} +operator + +@item @var{x} .- @var{y} +Element by element subtraction. This operator is equivalent to @code{-}. + +@item @var{x} * @var{y} +Matrix multiplication. The number of columns of @var{x} must agree +with the number of rows of @var{y}. + +@item @var{x} .* @var{y} +Element by element multiplication. If both operands are matrices, the +number of rows and columns must both agree. + +@item @var{x} / @var{y} +Right division. This is conceptually equivalent to the expression + +@example +(inverse (y') * x')' +@end example + +@noindent +but it is computed without forming the inverse of @var{y'}. + +If the matrix is singular then an error occurs. If the matrix is +under-determined, then a particular solution is found (but not minimum +norm). If the solution is over-determined, then an attempt is made +to find a solution, but this is not guaranteed to work. + +@item @var{x} ./ @var{y} +Element by element right division. + +@item @var{x} \ @var{y} +Left division. This is conceptually equivalent to the expression + +@example +inverse (x) * y +@end example + +@noindent +but it is computed without forming the inverse of @var{x}. + +If the matrix is singular then an error occurs. If the matrix is +under-determined, then a particular solution is found (but not minimum +norm). If the solution is over-determined, then an attempt is made +to find a solution, but this is not guaranteed to work. + +@item @var{x} .\ @var{y} +Element by element left division. Each element of @var{y} is divided +by each corresponding element of @var{x}. + +@item @var{x} ^ @var{y} +@itemx @var{x} ** @var{y} +Power operator. If @var{x} and @var{y} are both scalars, this operator +returns @var{x} raised to the power @var{y}. Otherwise @var{x} must +be a square matrix raised to an integer power. + +@item @var{x} .^ @var{y} +@item @var{x} .** @var{y} +Element by element power operator. If both operands are matrices, the +number of rows and columns must both agree. + +@end table + +@node Comparison operations, Polynomial manipulations, Arithmetic operations, Manipulating Galois Fields +@subsection Comparison operations + +Galois variables can be tested for equality in the usual manner. That is + +@example +octave:1> a = gf ([0:7], 3); +octave:2> a == ones (1, 8) +ans = + + 0 1 0 0 0 0 0 0 + +octave:3> a != zeros (1, 8) +ans = + + 0 1 1 1 1 1 1 1 +@end example + +Likewise, Galois vectors can be tested against scalar values (whether they are +Galois or not). For instance + +@example +octave:4> a == 1 +ans = + + 0 1 0 0 0 0 0 0 +@end example + +To test if any or all of the values in a Galois array are non-zero, the +functions @code{any} and @code{all} can be used as normally. + +In addition the comparison operators @code{>}, @code{>=}, @code{<} and +@code{<=} are available. As elements of the Galois Field are modulus +2^@var{m}, all elements of the field are both greater than and less than +all others at the same time. Thus these comparison operators don't make +that much sense and are only included for completeness. The comparison is +done relative to the integer value of the Galois Field elements. + +@node Polynomial manipulations, Linear Algebra, Comparison operations, Manipulating Galois Fields +@subsection Polynomial manipulations + +A polynomial in GF(2^M) can be expressed as a vector in GF(2^M). For instance +if @var{a} is the @emph{primitive element}, then the example + +@example +octave:1> poly = gf ([2, 4, 5, 1], 3); +@end example + +@noindent +represents the polynomial + +@tex +$$ +poly = a x^3 + a^2 x^2 + (a^2 + 1) x + 1 +$$ +@end tex +@ifnottex +@example +poly = @var{a} * x^3 + @var{a}^2 * x^2 + (@var{a}^2 + 1) * x + 1 +@end example +@end ifnottex + +Arithmetic can then be performed on these vectors. For instance to add +to polynomials an example is + +@example +octave:1> poly1 = gf ([2, 4, 5, 1], 3); +octave:2> poly2 = gf ([1, 2], 3); +octave:3> sumpoly = poly1 + [0, 0, poly2] +sumpoly = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 2 4 4 3 +@end example + +Note that @var{poly2} must be zero padded to the same length as poly1 to +allow the addition to take place. + +Multiplication and division of Galois polynomials is equivalent to convolution +and de-convolution of vectors of Galois elements. Thus to multiply two +polynomials in GF(2^3). + +@example +octave:4> mulpoly = conv (poly1, poly2) +mulpoly = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 2 0 6 0 2 +@end example + +Likewise the division of two polynomials uses the de-convolution function +as follows + +@example +octave:5> [poly, remd] = deconv (mulpoly, poly2) +poly = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 2 4 5 1 + +remd = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 0 0 0 0 0 +@end example + +Note that the remainder of this division is zero, as we performed the inverse +operation to the multiplication. + +To evaluate a polynomial for a certain value in GF(2^M), use the Octave +function @code{polyval}. + +@example +octave:1> poly1 = gf ([2, 4, 5, 1], 3); ## a*x^3+a^2*x^2+(a^2+1)*x+1 +octave:2> x0 = gf ([0, 1, 2], 3); +octave:3> y0 = polyval (poly1, x0); +y0 = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 1 2 0 + +octave:4> a = gf (2, 3); ## The primitive element +octave:5> y1 = a .* x0.^3 + a.^2 .* x0.^2 + (a.^2 + 1) .* x0 + 1 +y1 = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 1 2 0 +@end example + +It is equally possible to find the roots of Galois polynomials with the +@code{roots} function. Using the polynomial above over GF(2^3), we can +find its roots in the following manner + +@example +octave:1> poly1 = gf ([2, 4, 5, 1], 3); +octave:2> root1 = roots (poly1) +root1 = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 2 + 5 + 5 +@end example + +Thus the example polynomial has 3 roots in GF(2^3) with one root of +multiplicity 2. We can check this answer with the @code{polyval} function +as follows + +@example +octave:3> check1 = polyval (poly1, root1) +check1 = +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + +Array elements = + + 0 + 0 + 0 +@end example + +@noindent +which as expected gives a zero vector. It should be noted that both the +number of roots and their value, will depend on the chosen field. Thus +for instance + +@example +octave:1> poly3 = gf ([2, 4, 5, 1], 3, 13); +octave:2> root3 = roots (poly3) +root3 = +GF(2^3) array. Primitive Polynomial = D^3+D^2+1 (decimal 13) + +Array elements = + + 5 +@end example + +@noindent +shows that in the field GF(2^3) with a different primitive polynomial, +has only one root exists. + +The minimum polynomial of an element of GF(2^M) is the minimum degree +polynomial in GF(2), excluding the trivial zero polynomial, that has +that element as a root. The fact that the minimum polynomial is in GF(2) +means that its coefficients are one or zero only. The @code{minpol} +function can be used to find the minimum polynomial as follows + +@example +octave:1> a = gf (2, 3); ## The primitive element +octave:2> b = minpol (a) +b = +GF(2) array. + +Array elements = + + 1 0 1 1 +@end example + +Note that the minimum polynomial of the primitive element is the primitive +polynomial. Elements of GF(2^M) sharing the same minimum polynomial form a +partitioning of the field. This partitioning can be found with the +@code{cosets} function as follows + +@example +octave:1> c = cosets (3) +c = +@{ + [1,1] = + GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + + Array elements = + + 1 + + [1,2] = + GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + + Array elements = + + 2 4 6 + + [1,3] = + GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) + + Array elements = + + 3 5 7 + +@} +@end example + +@noindent +which returns a cell array containing all of the elements of the GF(2^3), +partitioned into groups sharing the same minimum polynomial. The function +@code{cosets} can equally accept a second argument defining the primitive +polynomial to use in its calculations (i.e. @code{cosets (@var{a}, @var{p})}). + +@node Linear Algebra, Signal Processing, Polynomial manipulations, Manipulating Galois Fields +@subsection Linear Algebra + +The basic linear algebra operation of this package is the LU factorization +of a Galois array. That is the Galois array @var{a} is factorized in the +following way + +@example +octave:2> [l, u, p] = lu (a) +@end example + +@noindent +such that @code{@var{p} * @var{a} = @var{l} * @var{u}}. The matrix @var{p} +contains row permutations of @var{a}, such that @var{l} and @var{u} are +strictly upper and low triangular. The Galois array @var{a} can be +rectangular. + +All other linear algebra operations within this package are based on this +LU factorization of a Galois array. An important consequence of this is that +no solution can be found for singular matrices, only a particular solution +will be found for under-determined systems of equation and the solution found +for over-determined systems is not always correct. This is identical to the +way @sc{matlab} performs linear algebra on Galois arrays. + +For instance consider the under-determined linear equation + +@example +octave:1> A = gf ([2, 0, 3, 3; 3, 1, 3, 1; 3, 1, 1, 0], 2); +octave:2> b = [0:2]'; +octave:3> x = A \ b; +@end example + +@noindent +gives the solution @code{@var{x} = [2, 0, 3, 2]}. There are in fact 4 +possible solutions to this linear system; @code{@var{x} = [3, 2, 2, 0]}, +@code{@var{x} = [0, 3, 1, 1]}, @code{@var{x} = [2, 0, 3, 2]} and +@code{@var{x} = [1, 1, 0, 3]}. No particular selection criteria are +applied to the chosen solution. + +In addition, because singular matrices cannot be solved, unless you +know the matrix is not singular, you should test the determinant of the +matrix prior to solving the linear system. For instance + +@example +octave:1> A = gf (floor (2^m * rand (3)), 2); +octave:2> b = [0:2]'; +octave:3> if (det (A) != 0); x = A \ b; y = b' / A; endif; +octave:4> r = rank (A); +@end example + +@noindent +solves the linear systems @code{@var{A} * @var{x} = @var{b}} and +@code{@var{y} * @var{A} = @var{b}}. Note that you do not need to take +into account rounding errors in the determinant, as the determinant can +only take values within the Galois Field. So if the determinant equals +zero, the array is singular. + +@node Signal Processing, , Linear Algebra, Manipulating Galois Fields +@subsection Signal Processing with Galois Fields + +Signal processing functions such as filtering, convolution, de-convolution +and Fourier transforms can be performed over Galois Fields. For instance +the @code{filter} function can be used with Galois vectors in the same +manner as usual. For instance + +@example +octave:1> b = gf ([2, 0, 0, 1, 0, 2, 0, 1], 2); +octave:2> a = gf ([2, 0, 1, 1], 2); +octave:3> x = gf ([1, zeros(1, 20)], 2); +octave:4> y = filter (b, a, x) +y = +GF(2^2) array. Primitive Polynomial = D^2+D+1 (decimal 7) + +Array elements = + + 1 0 3 0 2 3 1 0 1 3 3 1 0 1 3 3 1 0 1 3 3 +@end example + +@noindent +gives the impulse response of the filter defined by @var{a} and @var{b}. + +Two equivalent ways are given to perform the convolution of two Galois +vectors. Firstly the function @code{conv} can be used, or alternatively +the function @code{convmtx} can be used. The first of these function is +identical to the convolution function over real vectors, and has been +described in the section about multiplying two Galois polynomials. + +In the case where many Galois vectors will be convolved with the same +vector, the second function @code{convmtx} offers an alternative method +to calculate the convolution. If @var{a} is a column vector and @var{x} +is a column vector of length @var{n}, then + +@example +octave:1> m = 3; +octave:2> a = gf (floor (2^m * rand (4, 1)), m); +octave:3> b = gf (floor (2^m * rand (4, 1)), m); +octave:4> c0 = conv (a, b)'; +octave:5> c1 = convmtx (a, length (b)) * b; +octave:6> check = all (c0 == c1) +check = 1 +@end example + +@noindent +shows the equivalence of the two functions. The de-convolution function has +been previously described above. + +The final signal processing function available in this package are the +functions to perform Fourier transforms over a Galois field. Three +functions are available, @code{fft}, @code{ifft} and @code{dftmtx}. The +first two functions use the third to perform their work. Given an element +@var{a} of the Galois field GF(2^M), @code{dftmtx} returns the @code{2^M - 1} +square matrix used in the Fourier transforms with respect to @var{a}. The +minimum polynomial of @var{a} must be primitive in GF(2^M). In the case of +the @code{fft} function @code{dftmtx} is called with the primitive element of +the Galois Field as an argument. As an example + +@example +octave:1> m = 4; +octave:2> n = 2^m - 1; +octave:2> alph = gf (2, m); +octave:3> x = gf (floor (2^m * rand (n, 1)), m); +octave:4> y0 = fft (x); +octave:5> y1 = dftmtx (alph) * x; +octave:6> z0 = ifft (y0); +octave:7> z1 = dftmtx (1/alph) * y1; +octave:8> check = all (y0 == y1) & all (z0 == x) & all (z1 == x) +check = 1 +@end example + +In all cases, the length of the vector to be transformed must be +@code{2^M -1}. As the @code{dftmtx} creates a matrix representing the +Fourier transform, to limit the computational task only Fourier +transforms in GF(2^M), where M is less than or equal to 8, are supported. + +@node Function Reference, , Galois Fields, Top +@chapter Function Reference + +@REFERENCE_SECTION(Communications) + +@bye diff --git a/doc/commsimages.m b/doc/commsimages.m new file mode 100644 index 0000000..36eca98 --- /dev/null +++ b/doc/commsimages.m @@ -0,0 +1,87 @@ +## Copyright (C) 2007-2012 David Bateman +## Copyright (C) 2013 Mike Miller +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . +## . + +function commsimages (nm, typ) + graphics_toolkit ("gnuplot"); + set_print_size (); + hide_output (); + if (strcmp (typ, "png")) + set (0, "defaulttextfontname", "*"); + endif + if (strcmp (typ, "eps")) + d_typ = "-depsc2"; + else + d_typ = ["-d", typ]; + endif + + if (strcmp (nm, "awgn")) + x = 0:0.1:2*pi; + y = sin (x); + noisy = awgn (y, 10, "measured"); + plot (x, y, "r"); + hold on; + plot (x, noisy, "g--"); + axis ([0, 2*pi, -1.5, 1.5]); + print ([nm "." typ], d_typ); + elseif (strcmp (nm, "eyediagram")) + n = 50; + ovsp = 50; + x = 1:n; + xi = 1:1/ovsp:n-0.1; + y = randsrc (1, n, [1 + 1i, 1 - 1i, -1 - 1i, -1 + 1i]); + yi = interp1 (x, y, xi); + noisy = awgn (yi, 15, "measured"); + cf = gcf (); + set (cf, "tag", "eyediagram"); + eyediagram (noisy, ovsp, [], [], [], cf); + print ([nm "." typ], d_typ); + elseif (strcmp (nm, "scatterplot")) + n = 200; + ovsp = 5; + x = 1:n; + xi = 1:1/ovsp:n-0.1; + y = randsrc (1, n, [1 + 1i, 1 - 1i, -1 - 1i, -1 + 1i]); + yi = interp1 (x, y, xi); + noisy = awgn (yi, 15, "measured"); + cf = gcf (); + set (cf, "tag", "scatterplot"); + f = scatterplot (noisy, 1, 0, "b", cf); + hold on; + scatterplot (noisy, ovsp, 0, "r+", f); + print ([nm "." typ], d_typ); + else + error ("unrecognized plot requested"); + endif + hide_output (); +endfunction + +function set_print_size () + image_size = [5.0, 3.5]; # in inches, 16:9 format + border = 0; # For postscript use 50/72 + set (0, "defaultfigurepapertype", ""); + set (0, "defaultfigurepaperorientation", "landscape"); + set (0, "defaultfigurepapersize", image_size + 2*border); + set (0, "defaultfigurepaperposition", [border, border, image_size]); +endfunction + +## Use this function before plotting commands and after every call to +## print since print resets output to stdout (unfortunately, gnuplot +## can't pop output as it can the terminal type). +function hide_output () + f = figure (1); + set (f, "visible", "off"); +endfunction diff --git a/doc/images.mk b/doc/images.mk new file mode 100644 index 0000000..a97fe04 --- /dev/null +++ b/doc/images.mk @@ -0,0 +1,22 @@ +IMAGES = awgn.eps eyediagram.eps scatterplot.eps awgn.pdf eyediagram.pdf scatterplot.pdf awgn.png eyediagram.png scatterplot.png +IMAGES_EPS = awgn.eps eyediagram.eps scatterplot.eps +IMAGES_PDF = awgn.pdf eyediagram.pdf scatterplot.pdf +IMAGES_PNG = awgn.png eyediagram.png scatterplot.png +awgn.eps: commsimages.m + $(OCTAVE) --path=$(CURDIR)/../inst -f -q -H --eval "commsimages ('awgn', 'eps');" +eyediagram.eps: commsimages.m + $(OCTAVE) --path=$(CURDIR)/../inst -f -q -H --eval "commsimages ('eyediagram', 'eps');" +scatterplot.eps: commsimages.m + $(OCTAVE) --path=$(CURDIR)/../inst -f -q -H --eval "commsimages ('scatterplot', 'eps');" +awgn.pdf: commsimages.m + $(OCTAVE) --path=$(CURDIR)/../inst -f -q -H --eval "commsimages ('awgn', 'pdf');" +eyediagram.pdf: commsimages.m + $(OCTAVE) --path=$(CURDIR)/../inst -f -q -H --eval "commsimages ('eyediagram', 'pdf');" +scatterplot.pdf: commsimages.m + $(OCTAVE) --path=$(CURDIR)/../inst -f -q -H --eval "commsimages ('scatterplot', 'pdf');" +awgn.png: commsimages.m + $(OCTAVE) --path=$(CURDIR)/../inst -f -q -H --eval "commsimages ('awgn', 'png');" +eyediagram.png: commsimages.m + $(OCTAVE) --path=$(CURDIR)/../inst -f -q -H --eval "commsimages ('eyediagram', 'png');" +scatterplot.png: commsimages.m + $(OCTAVE) --path=$(CURDIR)/../inst -f -q -H --eval "commsimages ('scatterplot', 'png');" diff --git a/doc/images.sh b/doc/images.sh new file mode 100755 index 0000000..9722fd1 --- /dev/null +++ b/doc/images.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +images="awgn eyediagram scatterplot" +formats="eps pdf png" +script=commsimages.m + +printf "IMAGES =" +for fmt in $formats; do + for img in $images; do + printf " $img.$fmt" + done +done +printf "\n" + +for fmt in $formats; do + fmtupcase=`echo $fmt | awk '{print toupper($0)}'` + printf "IMAGES_$fmtupcase =" + for img in $images; do + printf " $img.$fmt" + done + printf "\n" +done + +for fmt in $formats; do + for img in $images; do + printf "$img.$fmt: commsimages.m\n" + printf "\t\$(OCTAVE) --path=\$(CURDIR)/../inst -f -q -H --eval \"commsimages ('$img', '$fmt');\"\n" + done +done diff --git a/doc/mkdoc.pl b/doc/mkdoc.pl new file mode 100755 index 0000000..0f2e1c9 --- /dev/null +++ b/doc/mkdoc.pl @@ -0,0 +1,160 @@ +#!/usr/bin/env perl +# +# David Bateman Feb 02 2003 +# +# Extracts the help in texinfo format from *.cc and *.m files for use +# in documentation. Based on make_index script from octave_forge. + +use strict; +use File::Find; +use File::Basename; +use FileHandle; + +my $docdir = "."; +if (@ARGV) { + $docdir = @ARGV[0]; +} + +# locate all C++ and m-files in current directory +my @m_files = (); +my @C_files = (); +find(\&cc_and_m_files, $docdir); + +sub cc_and_m_files { # {{{1 populates global array @files + return unless -f and /\.(m|cc)$/; # .m and .cc files + my $path = "$File::Find::dir/$_"; + $path =~ s|^[.]/||; + if (/\.m$/) { + push @m_files, $path; + } else { + push @C_files, $path; + } +} # 1}}} + +# grab help from C++ files +foreach my $f ( @C_files ) { + # XXX FIXME XXX. Should run the preprocessor over the file first, since + # the help might include defines that are compile dependent. + if ( open(IN,$f) ) { + while () { + # skip to the next function + next unless /^DEFUN_DLD/; + + # extract function name to pattern space + /\((\w*)\s*,/; + # remember function name + my $function = $1; + # skip to next line if comment doesn't start on this line + # XXX FIXME XXX maybe we want a loop here? + $_ = unless /\"/; + # skip to the beginning of the comment string by + # chopping everything up to opening " + my $desc = $_; + $desc =~ s/^[^\"]*\"//; + # join lines until you get the end of the comment string + # plus a bit more. You need the "plus a bit more" because + # C compilers allow implicitly concatenated string constants + # "A" "B" ==> "AB". + while ($desc !~ /[^\\]\"\s*\S/ && $desc !~ /^\"/) { + # if line ends in '\', chop it and the following '\n' + $desc =~ s/\\\s*\n//; + # join with the next line + $desc .= ; + # eliminate consecutive quotes, being careful to ignore + # preceding slashes. XXX FIXME XXX what about \\" ? + $desc =~ s/([^\\])\"\s*\"/$1/; + } + $desc = "" if $desc =~ /^\"/; # chop everything if it was "" + $desc =~ s/\\n/\n/g; # insert fake line ends + $desc =~ s/([^\"])\".*$/$1/; # chop everything after final '"' + $desc =~ s/\\\"/\"/; # convert \"; XXX FIXME XXX \\" + $desc =~ s/$//g; # chop trailing ... + + if (!($desc =~ /^\s*-[*]- texinfo -[*]-/)) { + my $err = sprintf("Function %s, does not contain texinfo help\n", + $function); + print STDERR "$err"; + } + my $entry = sprintf("\037%s\n%s", $function, $desc); + print "$entry", "\n"; + } + close (IN); + } else { + print STDERR "Could not open file ($f): $!\n"; + } +} + +# grab help from m-files +foreach my $f ( @m_files ) { + my $desc = extract_description($f); + my $function = basename($f, ('.m')); + die "Null function?? [$f]\n" unless $function; + if (!($desc =~ /^\s*-[*]- texinfo -[*]-/)) { + my $err = sprintf("Function %s, does not contain texinfo help\n", + $function); + print STDERR "$err"; + } + my $entry = sprintf("\037%s\n%s", $function, $desc); + print "$entry", "\n"; +} + +sub extract_description { # {{{1 +# grab the entire documentation comment from an m-file + my ($file) = @_; + my $retval = ''; + + if( open( IN, "$file")) { + # skip leading blank lines + while () { + last if /\S/; + } + if( m/\s*[%\#][\s\#%]* Copyright/) { + # next block is copyright statement, skip it + while () { + last unless /^\s*[%\#]/; + } + } + # Skip everything until the next comment block + while ( !/^\s*[\#%]+\s/ ) { + $_ = ; + last if not defined $_; + } + # Return the next comment block as the documentation + while (/^\s*[\#%]+\s/) { + s/^\s*[%\#]+\s//; # strip leading comment characters + s/[\cM\s]*$//; # strip trailing spaces. + s/[\.*]$//; + $retval .= "$_\n"; + $_ = ; + last if not defined $_; + } + close(IN); + return $retval; + } + else { + print STDERR "Could not open file ($file): $!\n"; + } +} # 1}}} +__END__ +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. +This program 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 General Public License for more details. +You should have received a copy of the GNU General Public License +along with this program; if not, see . +This program is granted to the public domain. +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. diff --git a/doc/mktexi.pl b/doc/mktexi.pl new file mode 100755 index 0000000..c6623e1 --- /dev/null +++ b/doc/mktexi.pl @@ -0,0 +1,457 @@ +#!/usr/bin/env perl +# +# David Bateman Feb 02 2003 +# +# Extracts the help in texinfo format for particular function for use +# in documentation. Based on make_index script from octave_forge. + +use strict; +use File::Find; +use File::Basename; +use Text::Wrap; +use FileHandle; +use IPC::Open3; +use POSIX ":sys_wait_h"; + +my $file = shift @ARGV; +my $docfile = shift @ARGV; +my $indexfile = shift @ARGV; +my $line; + +if ( open(IN,$file) ) { + $line = ; + my $tex = 0; + while ($line) { + if ($line =~ /^\@DOCSTRING/) { + my $found = 0; + my $func = $line; + $func =~ s/\@DOCSTRING\(//; + $func =~ s/\)[\n\r]+//; + my $func0 = $func; + my $func1 = $func; + $func0 =~ s/,.*$//; + $func1 =~ s/^.*,//; + if ( open(DOC,$docfile) ) { + while () { + next unless /\037/; + my $function = $_; + $function =~ s/\037//; + $function =~ s/[\n\r]+//; + if ($function =~ /^$func0$/) { + my $desc = ""; + my $docline; + my $doctex = 0; + while (($docline = ) && ($docline !~ /^\037/)) { + $docline =~ s/^\s*-[*]- texinfo -[*]-\s*//; + if ($docline =~ /\@tex/) { + $doctex = 1; + } + if ($doctex) { + $docline =~ s/\\\\/\\/g; + } + if ($docline =~ /\@end tex/) { + $doctex = 0; + } + $desc .= $docline; + } + $desc =~ s/$func0/$func1/g; + $desc =~ s/\@seealso\{(.*[^}])\}/See also: \1/g; + print "$desc", "\n"; + $found = 1; + last; + } + } + close (DOC); + if (! $found) { + print "\@emph{Not implemented}\n"; + } + } else { + print STDERR "Could not open file $docfile\n"; + exit 1; + } + } elsif ($line =~ /^\@REFERENCE_SECTION/) { + my $secfound = 0; + my $sec = $line; + $sec =~ s/\@REFERENCE_SECTION\(//; + $sec =~ s/\)[\n\r]+//; + my @listfunc = (); + my $nfunc = 0; + my $seccat = 0; + + if ( open(IND,$indexfile) ) { + while () { + next unless /^[^ ]/; + my $section = $_; + $section =~ s/[\n\r]+//; + if ($section =~ /^(.*?)\s*>>\s*(.*?)$/) { + $section =~ s/.*>>(.*)/\1/; + $seccat = 1; + } + $section =~ s/^ *//; + $section =~ s/ *$//; + if ($section =~ /^$sec$/) { + if ($seccat) { + print "\@iftex\n"; + print "\@section Functions by Category\n"; + # Get the list of categories to index + my $firstcat = 1; + my $category; + while () { + last if />>/; + if (/^[^ ]/) { + if (! $firstcat) { + print "\@end table\n"; + } else { + $firstcat = 0; + } + $category = $_; + $category =~ s/[\n\r]+//; + print "\@subsection $category\n"; + print "\@table \@asis\n"; + } elsif (/^\s+(\S.*\S)\s*=\s*(\S.*\S)\s*$/) { + my $func = $1; + my $desc = $2; + print "\@item $func\n"; + print "$desc\n"; + print "\n"; + } else { + if ($firstcat) { + print STDERR "Error parsing index file\n"; + exit 1; + } + s/^\s+//; + my @funcs = split /\s+/; + while ($#funcs >= 0) { + my $func = shift @funcs; + $func =~ s/^ *//; + $func =~ s/[\n\r]+//; + push @listfunc, $func; + $nfunc = $nfunc + 1; + print "\@item $func\n"; + print func_summary($func, $docfile); + print "\n"; + } + } + } + if (! $firstcat) { + print "\@end table\n"; + } + print "\@end iftex\n\n"; + print "\n\@section Functions Alphabetically\n"; + } else { + # Get the list of functions to index + my $indline; + while (($indline = ) && ($indline =~ /^ /)) { + if ($indline =~ /^\s+(\S.*\S)\s*=\s*(\S.*\S)\s*$/) { + next; + } + $indline =~ s/^\s+//; + my @funcs = split(/\s+/,$indline); + while ($#funcs >= 0) { + my $func = shift @funcs; + $func =~ s/^ *//; + $func =~ s/[\n\r]+//; + push @listfunc, $func; + $nfunc = $nfunc + 1; + } + } + } + $secfound = 1; + last; + } + } + close (IND); + if (! $secfound) { + print STDERR "Did not find section $sec\n"; + } + } else { + print STDERR "Could not open file $indexfile\n"; + exit 1; + } + + @listfunc = sort(@listfunc); + my @listfunc2 = (); + my $indent = 16 - 3; + print "\@menu\n"; + foreach my $func (@listfunc) { + if ( open(DOC,$docfile) ) { + my $found = 0; + while () { + next unless /\037/; + my $function = $_; + $function =~ s/\037//; + $function =~ s/[\n\r]+//; + if ($function =~ /^$func$/) { + $found = 1; + last; + } + } + close (DOC); + if ($found) { + push @listfunc2, $func; + my $func0 = "${func}::"; + my $entry = sprintf("* %-*s %s",$indent,$func0,func_summary($func,$docfile)); + print wrap("","\t\t","$entry"), "\n"; + } + } else { + print STDERR "Could not open file $indexfile\n"; + exit 1; + } + } + print "\@end menu\n"; + + my $up = "Function Reference"; + my $next; + my $prev; + my $mfunc = 1; + foreach my $func (@listfunc2) { + if ($mfunc == $nfunc) { + $next = ""; + } else { + $next = @listfunc2[$mfunc]; + $mfunc = $mfunc + 1; + } + print "\n\@node $func, $next, $prev, $up\n"; + if ($seccat) { + print "\@subsection $func\n\n"; + } else { + print "\@section $func\n\n"; + } + $prev = $func; + my $found = 0; + my $desc = ""; + if ( open(DOC,$docfile) ) { + while () { + next unless /\037/; + my $function = $_; + $function =~ s/\037//; + $function =~ s/[\n\r]+//; + if ($function =~ /^$func$/) { + my $docline; + my $doctex = 0; + while (($docline = ) && ($docline !~ /^\037/)) { + $docline =~ s/^\s*-[*]- texinfo -[*]-\s*//; + if ($docline =~ /\@tex/) { + $doctex = 1; + } + if ($doctex) { + $docline =~ s/\\\\/\\/g; + } + if ($docline =~ /\@end tex/) { + $doctex = 0; + } + $desc .= $docline; + } + $desc =~ s/\@seealso\{(.*[^}])\}/See also: \1/g; + print "$desc", "\n"; + $found = 1; + last; + } + } + close (DOC); + if (! $found) { + print "\@emph{Not implemented}\n"; + } + } else { + print STDERR "Could not open file $docfile\n"; + exit 1; + } + } + } else { + if ($line =~ /\@tex/) { + $tex = 1; + } + if ($tex) { + $line =~ s/\\\\/\\/g; + } + print "$line"; + if ($line =~ /\@end tex/) { + $tex = 0; + } + } + $line = ; + } +} else { + print STDERR "Could not open file $file\n"; + exit 1; +} + +sub func_summary { # {{{1 + my ($func, # in function name + $docfile # in DOCSTRINGS + ) = @_; + + my $desc = ""; + my $found = 0; + if ( open(DOC,$docfile) ) { + while () { + next unless /\037/; + my $function = $_; + $function =~ s/\037//; + $function =~ s/[\n\r]+//; + if ($function =~ /^$func$/) { + my $docline; + my $doctex = 0; + while (($docline = ) && ($docline !~ /^\037/)) { + if ($docline =~ /\@tex/) { + $doctex = 1; + } + if ($doctex) { + $docline =~ s/\\\\/\\/g; + } + if ($docline =~ /\@end tex/) { + $doctex = 0; + } + $desc .= $docline; + } + $desc =~ s/\@seealso\{(.*[^}])\}/See also: \1/g; + $found = 1; + last; + } + } + close (DOC); + if (! $found) { + $desc = "\@emph{Not implemented}"; + } + } else { + print STDERR "Could not open file $docfile\n"; + exit 1; + } + return first_sentence($desc); +} # 1}}} + + +sub first_sentence { # {{{1 +# grab the first real sentence from the function documentation + my ($desc) = @_; + my $retval = ''; + my $line; + my $next; + my @lines; + + my $trace = 0; + # $trace = 1 if $desc =~ /Levenberg/; + return "" unless defined $desc; + if ($desc =~ /^\s*-[*]- texinfo -[*]-/) { + # help text contains texinfo. Strip the indicator and run it + # through makeinfo. (XXX FIXME XXX this needs to be a function) + $desc =~ s/^\s*-[*]- texinfo -[*]-\s*//; + my $cmd = "makeinfo --fill-column 1600 --no-warn --no-validate --no-headers --force --ifinfo"; + open3(*Writer, *Reader, *Errer, $cmd) or die "Could not run info"; + print Writer "\@macro seealso {args}\n\n\@noindent\nSee also: \\args\\.\n\@end macro\n"; + print Writer "$desc"; close(Writer); + @lines = ; close(Reader); + my @err = ; close(Errer); + waitpid(-1,&WNOHANG); + + # Display source and errors, if any + if (@err) { + my $n = 1; + foreach $line ( split(/\n/,$desc) ) { + printf "%2d: %s\n",$n++,$line; + } + print ">>> @err"; + } + + # Print trace showing formatted output +# print "\n"; + + # Skip prototype and blank lines + while (1) { + return "" unless @lines; + $line = shift @lines; + next if $line =~ /^\s*-/; + next if $line =~ /^\s*$/; + last; + } + + } else { + +# print "\n"; + + # Skip prototype and blank lines + @lines = split(/\n/,$desc); + while (1) { + return "" if ($#lines < 0); + $line = shift @lines; + next if $line =~ /^\s*[Uu][Ss][Aa][Gg][Ee]/; # skip " usage " + + $line =~ s/^\s*\w+\s*://; # chop " blah : " + print "strip blah: $line\n" if $trace; + $line =~ s/^\s*[Ff]unction\s+//; # chop " function " + print "strip function $line\n" if $trace; + $line =~ s/^\s*\[.*\]\s*=\s*//; # chop " [a,b] = " + print "strip []= $line\n" if $trace; + $line =~ s/^\s*\w+\s*=\s*//; # chop " a = " + print "strip a= $line\n" if $trace; + $line =~ s/^\s*\w+\s*\([^\)]*\)\s*//; # chop " f(x) " + print "strip f(x) $line\n" if $trace; + $line =~ s/^\s*[;:]\s*//; # chop " ; " + print "strip ; $line\n" if $trace; + + $line =~ s/^\s*[[:upper:]][[:upper:]0-9_]+//; # chop " BLAH" + print "strip BLAH $line\n" if $trace; + $line =~ s/^\s*\w*\s*[-]+\s+//; # chop " blah --- " + print "strip blah --- $line\n" if $trace; + $line =~ s/^\s*\w+ *\t\s*//; # chop " blah " + print "strip blah $line\n" if $trace; + $line =~ s/^\s*\w+\s\s+//; # chop " blah " + print "strip blah $line\n" if $trace; + +# next if $line =~ /^\s*\[/; # skip [a,b] = f(x) +# next if $line =~ /^\s*\w+\s*(=|\()/; # skip a = f(x) OR f(x) + next if $line =~ /^\s*or\s*$/; # skip blah \n or \n blah + next if $line =~ /^\s*$/; # skip blank line + next if $line =~ /^\s?!\//; # skip # !/usr/bin/octave + # XXX FIXME XXX should be testing for unmatched () in proto + # before going to the next line! + last; + } + } + + # Try to make a complete sentence, including the '.' + if ( "$line " !~ /[^.][.]\s/ && $#lines >= 0) { + my $next = $lines[0]; + $line =~ s/\s*$//; # trim trailing blanks on last + $next =~ s/^\s*//; # trim leading blanks on next + $line .= " $next" if "$next " =~ /[^.][.]\s/; # ends the sentence + } + + # Tidy up the sentence. + chomp $line; # trim trailing newline, if there is one + $line =~ s/^\s*//; # trim leading blanks on line + $line =~ s/([^.][.])\s.*$/$1/; # trim everything after the sentence + print "Skipping:\n$desc---\n" if $line eq ""; + + # And return it. + return $line; + +} # 1}}} + +__END__ +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. +This program 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 General Public License for more details. +You should have received a copy of the GNU General Public License +along with this program; if not, see . +This program is granted to the public domain. +THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +SUCH DAMAGE. diff --git a/inst/@galois/conv.m b/inst/@galois/conv.m new file mode 100644 index 0000000..0c606e1 --- /dev/null +++ b/inst/@galois/conv.m @@ -0,0 +1,85 @@ +## Copyright (C) 2002 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} conv (@var{a}, @var{b}) +## Convolve two Galois vectors. +## +## @code{y = conv (a, b)} returns a vector of length equal to +## @code{length (a) + length (b) - 1}. +## If @var{a} and @var{b} are polynomial coefficient vectors, @code{conv} +## returns the coefficients of the product polynomial. +## @seealso{deconv} +## @end deftypefn + +function y = conv (a, b) + + if (nargin != 2) + print_usage (); + endif + + if (!isgalois (a) && !isgalois (b)) + error ("conv: at least one argument must be a galois variable"); + elseif (!isgalois (a)) + a = gf (a, b.m, b.prim_poly); + elseif (!isgalois (b)) + b = gf (b, a.m, a.prim_poly); + elseif (a.m != b.m && a.prim_poly != b.prim_poly) + error ("conv: both vectors must be in the same galois field"); + endif + + if (min (size (a)) > 1 || min (size (b)) > 1) + error ("conv: both arguments must be vectors"); + endif + + la = length (a); + lb = length (b); + + ly = la + lb - 1; + + ## Ensure that both vectors are row vectors. + if (rows (a) > 1) + a = reshape (a, 1, la); + endif + if (rows (b) > 1) + b = reshape (b, 1, lb); + endif + + ## Use the shortest vector as the coefficent vector to filter. + if (la < lb) + if (ly > lb) + ## Can't concatenate galois variables like this yet + ## x = [b, (zeros (1, ly - lb))]; + x = gf ([b, (zeros (1, ly - lb))], b.m, b.prim_poly); + else + x = b; + endif + y = filter (a, 1, x); + else + if (ly > la) + ## Can't concatenate galois variables like this yet + ## x = [a, (zeros (1, ly - la))]; + x = gf ([a, (zeros (1, ly - la))], a.m, a.prim_poly); + else + x = a; + endif + y = filter (b, 1, x); + endif + +endfunction + +%%Test input validation +%!error conv (gf (1, 2), gf (1, 3)) +%!error conv (gf (eye (3), 3), gf (eye (3), 3)) diff --git a/inst/@galois/convmtx.m b/inst/@galois/convmtx.m new file mode 100644 index 0000000..148ab05 --- /dev/null +++ b/inst/@galois/convmtx.m @@ -0,0 +1,47 @@ +## Copyright (C) 2003 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} convmtx (@var{a}, @var{n}) +## +## Create matrix to perform repeated convolutions with the same vector +## in a Galois Field. If @var{a} is a column vector and @var{x} is a +## column vector of length @var{n}, in a Galois Field then +## +## @code{convmtx (@var{a}, @var{n}) * @var{x}} +## +## gives the convolution of of @var{a} and @var{x} and is the +## same as @code{conv (@var{a}, @var{x})}. The difference is if +## many vectors are to be convolved with the same vector, then +## this technique is possibly faster. +## +## Similarly, if @var{a} is a row vector and @var{x} is a row +## vector of length @var{n}, then +## +## @code{@var{x} * convmtx (@var{a}, @var{n})} +## +## is the same as @code{conv (@var{x}, @var{a})}. +## @seealso{conv} +## @end deftypefn + +function b = convmtx (a, n) + + if (!isgalois (a)) + error ("convmtx: argument must be a galois variable"); + endif + + b = gf (convmtx (a.x, n), a.m, a.prim_poly); + +endfunction diff --git a/inst/@galois/deconv.m b/inst/@galois/deconv.m new file mode 100644 index 0000000..779d037 --- /dev/null +++ b/inst/@galois/deconv.m @@ -0,0 +1,83 @@ +## Copyright (C) 2002 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} deconv (@var{y}, @var{a}) +## Deconvolve two Galois vectors. +## +## @code{[b, r] = deconv (y, a)} solves for @var{b} and @var{r} such that +## @code{y = conv (a, b) + r}. +## +## If @var{y} and @var{a} are polynomial coefficient vectors, @var{b} will +## contain the coefficients of the polynomial quotient and @var{r} will be +## a remainder polynomial of lowest order. +## @seealso{conv} +## @end deftypefn + +function [b, r] = deconv (y, a) + + if (nargin != 2) + print_usage (); + endif + + if (!isgalois (y) && !isgalois (a)) + error ("deconv: at least one argument must be a galois variable"); + elseif (!isgalois (y)) + y = gf (y, a.m, a.prim_poly); + elseif (!isgalois (a)) + a = gf (a, y.m, y.prim_poly); + elseif (a.m != y.m && a.prim_poly != y.prim_poly) + error ("deconv: both vectors must be in the same galois field"); + endif + + if (min (size (a)) > 1 || min (size (y)) > 1) + error ("deconv: both arguments must be vectors"); + endif + + la = length (a); + ly = length (y); + + lb = ly - la + 1; + + ## Ensure that both vectors are row vectors. + if (rows (a) > 1) + a = reshape (a, 1, la); + endif + if (rows (y) > 1) + y = reshape (y, 1, ly); + endif + + if (ly > la) + b = filter (y, a, [1, (zeros (1, ly - la))]); + elseif (ly == la) + b = filter (y, a, 1); + else + b = gf (0, y.m, y.prim_poly); + endif + + lc = la + length (b) - 1; + if (ly == lc) + r = y - conv (a, b); + else + ## Can't concatenate galois variables like this yet + ## r = [(zeros (1, lc - ly)), y] - conv (a, b); + r = gf ([(zeros (1, lc - ly)), y], y.m, y.prim_poly) - conv (a, b); + endif + +endfunction + +%%Test input validation +%!error deconv (gf (1, 2), gf (1, 3)) +%!error deconv (gf (eye (3), 3), gf (eye (3), 3)) diff --git a/inst/@galois/det.m b/inst/@galois/det.m new file mode 100644 index 0000000..bcd2ec9 --- /dev/null +++ b/inst/@galois/det.m @@ -0,0 +1,26 @@ +## Copyright (C) 2011 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Loadable Function} {@var{d} =} det (@var{a}) +## Compute the determinant of the Galois array @var{a}. +## @end deftypefn + +function varargout = det (varargin) + + varargout = cell (1, max (1, nargout)); + [varargout{:}] = gdet (varargin{:}); + +endfunction diff --git a/inst/@galois/dftmtx.m b/inst/@galois/dftmtx.m new file mode 100644 index 0000000..6b0b3a9 --- /dev/null +++ b/inst/@galois/dftmtx.m @@ -0,0 +1,71 @@ +## Copyright (C) 2002 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{d} =} dftmtx (@var{a}) +## +## Form a matrix, that can be used to perform Fourier transforms in +## a Galois Field. +## +## Given that @var{a} is an element of the Galois Field GF(2^m), and +## that the minimum value for @var{k} for which @code{@var{a} ^ @var{k}} +## is equal to one is @code{2^m - 1}, then this function produces a +## @var{k}-by-@var{k} matrix representing the discrete Fourier transform +## over a Galois Field with respect to @var{a}. The Fourier transform of +## a column vector is then given by @code{dftmtx (@var{a}) * @var{x}}. +## +## The inverse Fourier transform is given by @code{dftmtx (1 / @var{a})} +## @end deftypefn + +function d = dftmtx (a) + + if (nargin != 1) + print_usage (); + endif + + if (!isgalois (a)) + error ("dftmtx: argument must be a galois variable"); + endif + + m = a.m; + prim = a.prim_poly; + n = 2^a.m - 1; + if (n > 255) + error (["dftmtx: argument must be in Galois Field GF(2^M)" ... + ", where M is in the range [1,8]"]); + endif + + if (length (a) != 1) + error ("dftmtx: argument must be a scalar"); + endif + + mp = minpol (a); + if (mp(1) != 1 || !isprimitive (mp)) + error ("dftmtx: argument must be a primitive nth root of unity"); + endif + + step = log (a); + step = step.x; + row = exp (gf ([0:n-1], m, prim)); + d = zeros (n); + for i = 1:n; + d(i,:) = row .^ mod (step*(i-1), n); + endfor + +endfunction + +%%Test input validation +%!error dftmtx (gf (1, 12)) +%!error dftmtx (gf (eye (3), 4)) diff --git a/inst/@galois/diag.m b/inst/@galois/diag.m new file mode 100644 index 0000000..1119bc3 --- /dev/null +++ b/inst/@galois/diag.m @@ -0,0 +1,44 @@ +## Copyright (C) 2011 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Loadable Function} {} diag (@var{v}, @var{k}) +## Return a diagonal matrix with Galois vector @var{v} on diagonal @var{k}. +## The second argument is optional. If it is positive, the vector is placed on +## the @var{k}-th super-diagonal. If it is negative, it is placed on the +## @var{-k}-th sub-diagonal. The default value of @var{k} is 0, and the +## vector is placed on the main diagonal. For example, +## +## @example +## diag (gf ([1, 2, 3], 2), 1) +## ans = +## GF(2^2) array. Primitive Polynomial = D^2+D+1 (decimal 7) +## +## Array elements = +## +## 0 1 0 0 +## 0 0 2 0 +## 0 0 0 3 +## 0 0 0 0 +## +## @end example +## @end deftypefn + +function varargout = diag (varargin) + + varargout = cell (1, max (1, nargout)); + [varargout{:}] = gdiag (varargin{:}); + +endfunction diff --git a/inst/@galois/exp.m b/inst/@galois/exp.m new file mode 100644 index 0000000..b386a88 --- /dev/null +++ b/inst/@galois/exp.m @@ -0,0 +1,27 @@ +## Copyright (C) 2011 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Loadable Function} {} exp (@var{x}) +## Compute the anti-logarithm for each element of @var{x} for a Galois +## array. +## @end deftypefn + +function varargout = exp (varargin) + + varargout = cell (1, max (1, nargout)); + [varargout{:}] = gexp (varargin{:}); + +endfunction diff --git a/inst/@galois/fft.m b/inst/@galois/fft.m new file mode 100644 index 0000000..a4dce2d --- /dev/null +++ b/inst/@galois/fft.m @@ -0,0 +1,53 @@ +## Copyright (C) 2002 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} fft (@var{x}) +## +## If @var{x} is a column vector, finds the FFT over the primitive element +## of the Galois Field of @var{x}. If @var{x} is in the Galois Field +## GF(2^@var{m}), then @var{x} must have @code{2^@var{m} - 1} elements. +## @end deftypefn + +function y = fft (x) + + if (nargin != 1) + print_usage (); + endif + + if (!isgalois (x)) + error ("fft: argument must be a galois variable"); + endif + + n = 2^x.m - 1; + if (n > 255) + error (["fft: argument must be in Galois Field GF(2^M)" ... + ", where M is in the range [1,8]"]); + endif + + alph = gf (2, x.m, x.prim_poly); + [nr, nc] = size (x); + if (nc == 1 && nr == n) + y = dftmtx (alph) * x; + elseif (nc == n && nr == 1) + y = (dftmtx (alph) * x')'; + else + error ("fft: argument must be a vector in GF(2^M) of length 2^M-1"); + endif + +endfunction + +%%Test input validation +%!error fft (gf (1, 12)) diff --git a/inst/@galois/filter.m b/inst/@galois/filter.m new file mode 100644 index 0000000..283ad12 --- /dev/null +++ b/inst/@galois/filter.m @@ -0,0 +1,88 @@ +## Copyright (C) 2011 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Loadable Function} {y =} filter (@var{b}, @var{a}, @var{x}) +## @deftypefnx {Loadable Function} {[@var{y}, @var{sf}] =} filter (@var{b}, @var{a}, @var{x}, @var{si}) +## +## Digital filtering of vectors in a Galois Field. Returns the solution to +## the following linear, time-invariant difference equation over a Galois +## Field: +## @tex +## $$ +## \\sum_{k=0}^N a_{k+1} y_{n-k} = \\sum_{k=0}^M b_{k+1} x_{n-k}, \\qquad +## 1 \\le n \\le P +## $$ +## @end tex +## @ifnottex +## +## @smallexample +## @group +## N M +## SUM a(k+1) y(n-k) = SUM b(k+1) x(n-k) for 1<=n<=length(x) +## k=0 k=0 +## @end group +## @end smallexample +## @end ifnottex +## +## @noindent +## where +## @tex +## $a \\in \\Re^{N-1}$, $b \\in \\Re^{M-1}$, and $x \\in \\Re^P$. +## @end tex +## @ifnottex +## N=length(a)-1 and M=length(b)-1. +## @end ifnottex +## An equivalent form of this equation is: +## @tex +## $$ +## y_n = -\\sum_{k=1}^N c_{k+1} y_{n-k} + \\sum_{k=0}^M d_{k+1} x_{n-k}, \\qquad +## 1 \\le n \\le P +## $$ +## @end tex +## @ifnottex +## +## @smallexample +## @group +## N M +## y(n) = - SUM c(k+1) y(n-k) + SUM d(k+1) x(n-k) for 1<=n<=length(x) +## k=1 k=0 +## @end group +## @end smallexample +## @end ifnottex +## +## @noindent +## where +## @tex +## $c = a/a_1$ and $d = b/a_1$. +## @end tex +## @ifnottex +## c = a/a(1) and d = b/a(1). +## @end ifnottex +## +## If the fourth argument @var{si} is provided, it is taken as the +## initial state of the system and the final state is returned as +## @var{sf}. The state vector is a column vector whose length is +## equal to the length of the longest coefficient vector minus one. +## If @var{si} is not supplied, the initial state vector is set to all +## zeros. +## @end deftypefn + +function varargout = filter (varargin) + + varargout = cell (1, max (1, nargout)); + [varargout{:}] = gfilter (varargin{:}); + +endfunction diff --git a/inst/@galois/ifft.m b/inst/@galois/ifft.m new file mode 100644 index 0000000..06421d1 --- /dev/null +++ b/inst/@galois/ifft.m @@ -0,0 +1,54 @@ +## Copyright (C) 2002 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} ifft (@var{x}) +## +## If @var{x} is a column vector, finds the IFFT over the primitive element +## of the Galois Field of @var{x}. If @var{x} is in the Galois Field +## GF(2^@var{m}), then @var{x} must have @code{2^@var{m} - 1} elements. +## @seealso{ifft} +## @end deftypefn + +function y = ifft (x) + + if (nargin != 1) + print_usage (); + endif + + if (!isgalois (x)) + error ("ifft: argument must be a galois variable"); + endif + + n = 2^x.m - 1; + if (n > 255) + error (["ifft: argument must be in Galois Field GF(2^M)" ... + ", where M is in the range [1,8]"]); + endif + + alph = gf (2, x.m, x.prim_poly); + [nr, nc] = size (x); + if (nc == 1 && nr == n) + y = dftmtx (1/alph) * x; + elseif (nc == n && nr == 1) + y = (dftmtx (1/alph) * x')'; + else + error ("ifft: argument must be a vector in GF(2^M) of length 2^M-1"); + endif + +endfunction + +%%Test input validation +%!error ifft (gf (1, 12)) diff --git a/inst/@galois/inv.m b/inst/@galois/inv.m new file mode 100644 index 0000000..ac96003 --- /dev/null +++ b/inst/@galois/inv.m @@ -0,0 +1,28 @@ +## Copyright (C) 2011 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Loadable Function} {[@var{x}, @var{rcond}] =} inv (@var{a}) +## Compute the inverse of the square matrix @var{a}. Return an estimate +## of the reciprocal condition number if requested, otherwise warn of an +## ill-conditioned matrix if the reciprocal condition number is small. +## @end deftypefn + +function varargout = inv (varargin) + + varargout = cell (1, max (1, nargout)); + [varargout{:}] = ginv (varargin{:}); + +endfunction diff --git a/inst/@galois/inverse.m b/inst/@galois/inverse.m new file mode 100644 index 0000000..9b25945 --- /dev/null +++ b/inst/@galois/inverse.m @@ -0,0 +1,26 @@ +## Copyright (C) 2011 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Loadable Function} {[@var{x}, @var{rcond}] =} inverse (@var{a}) +## See inv. +## @end deftypefn + +function varargout = inverse (varargin) + + varargout = cell (1, max (1, nargout)); + [varargout{:}] = ginverse (varargin{:}); + +endfunction diff --git a/inst/@galois/isequal.m b/inst/@galois/isequal.m new file mode 100644 index 0000000..9f9aee7 --- /dev/null +++ b/inst/@galois/isequal.m @@ -0,0 +1,36 @@ +## Copyright (C) 2000 Paul Kienzle +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} isequal (@var{x1}, @var{x2}, @dots{}) +## Return true if all of @var{x1}, @var{x2}, @dots{} are equal. +## @seealso{isequalwithequalnans} +## @end deftypefn + +function t = isequal (x, varargin) + + if (nargin < 2) + print_usage (); + endif + + for arg = 1:length (varargin) + y = varargin{arg}; + t = all (x(:) == y(:)); + if (!t) + return + endif + endfor + +endfunction diff --git a/inst/@galois/log.m b/inst/@galois/log.m new file mode 100644 index 0000000..0654b9f --- /dev/null +++ b/inst/@galois/log.m @@ -0,0 +1,27 @@ +## Copyright (C) 2011 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Loadable Function} {} log (@var{x}) +## Compute the natural logarithm for each element of @var{x} for a Galois +## array. +## @end deftypefn + +function varargout = log (varargin) + + varargout = cell (1, max (1, nargout)); + [varargout{:}] = glog (varargin{:}); + +endfunction diff --git a/inst/@galois/lu.m b/inst/@galois/lu.m new file mode 100644 index 0000000..9e0b310 --- /dev/null +++ b/inst/@galois/lu.m @@ -0,0 +1,68 @@ +## Copyright (C) 2011 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Loadable Function} {[@var{l}, @var{u}, @var{p}] =} lu (@var{a}) +## @cindex LU decomposition of Galois matrix +## Compute the LU decomposition of @var{a} in a Galois Field. The result is +## returned in a permuted form, according to the optional return value +## @var{p}. For example, given the matrix +## @code{a = gf ([1, 2; 3, 4], 3)}, +## +## @example +## [l, u, p] = lu (a) +## @end example +## +## @noindent +## returns +## +## @example +## l = +## GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) +## +## Array elements = +## +## 1 0 +## 6 1 +## +## u = +## GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) +## +## Array elements = +## +## 3 4 +## 0 7 +## +## p = +## +## Permutation Matrix +## +## 0 1 +## 1 0 +## +## @end example +## +## Such that @code{@var{p} * @var{a} = @var{l} * @var{u}}. If the argument +## @var{p} is not included then the permutations are applied to @var{l} +## so that @code{@var{a} = @var{l} * @var{u}}. @var{l} is then a pseudo- +## lower triangular matrix. The matrix @var{a} can be rectangular. +## @end deftypefn + +function varargout = lu (varargin) + + varargout = cell (1, max (1, nargout)); + [varargout{:}] = glu (varargin{:}); + +endfunction diff --git a/inst/@galois/prod.m b/inst/@galois/prod.m new file mode 100644 index 0000000..bdbe584 --- /dev/null +++ b/inst/@galois/prod.m @@ -0,0 +1,27 @@ +## Copyright (C) 2011 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Loadable Function} {} prod (@var{x}, @var{dim}) +## Product of elements along dimension @var{dim} of Galois array. If +## @var{dim} is omitted, it defaults to 1 (column-wise products). +## @end deftypefn + +function varargout = prod (varargin) + + varargout = cell (1, max (1, nargout)); + [varargout{:}] = gprod (varargin{:}); + +endfunction diff --git a/inst/@galois/rank.m b/inst/@galois/rank.m new file mode 100644 index 0000000..351eadb --- /dev/null +++ b/inst/@galois/rank.m @@ -0,0 +1,27 @@ +## Copyright (C) 2011 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Loadable Function} {@var{d} =} rank (@var{a}) +## Compute the rank of the Galois array @var{a} by counting the independent +## rows and columns. +## @end deftypefn + +function varargout = rank (varargin) + + varargout = cell (1, max (1, nargout)); + [varargout{:}] = grank (varargin{:}); + +endfunction diff --git a/inst/@galois/reshape.m b/inst/@galois/reshape.m new file mode 100644 index 0000000..0234ad2 --- /dev/null +++ b/inst/@galois/reshape.m @@ -0,0 +1,58 @@ +## Copyright (C) 2011 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Loadable Function} {} reshape (@var{a}, @var{m}, @var{n}) +## Return a matrix with @var{m} rows and @var{n} columns whose elements are +## taken from the Galois array @var{a}. To decide how to order the elements, +## Octave pretends that the elements of a matrix are stored in column-major +## order (like Fortran arrays are stored). +## +## For example, +## +## @example +## reshape (gf ([1, 2, 3, 4], 3), 2, 2) +## ans = +## GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11) +## +## Array elements = +## +## 1 3 +## 2 4 +## +## @end example +## +## The @code{reshape} function is equivalent to +## +## @example +## @group +## retval = gf (zeros (m, n), a.m, a.prim_poly); +## retval(:) = a; +## @end group +## @end example +## +## @noindent +## but it is somewhat less cryptic to use @code{reshape} instead of the +## colon operator. Note that the total number of elements in the original +## matrix must match the total number of elements in the new matrix. +## @seealso{:} +## @end deftypefn + +function varargout = reshape (varargin) + + varargout = cell (1, max (1, nargout)); + [varargout{:}] = greshape (varargin{:}); + +endfunction diff --git a/inst/@galois/roots.m b/inst/@galois/roots.m new file mode 100644 index 0000000..3c5fdab --- /dev/null +++ b/inst/@galois/roots.m @@ -0,0 +1,76 @@ +## Copyright (C) 2002 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} roots (@var{v}) +## +## For a vector @var{v} with @math{N} components, return +## the roots of the polynomial over a Galois Field +## @tex +## $$ +## v_1 z^{N-1} + \cdots + v_{N-1} z + v_N. +## $$ +## @end tex +## @ifnottex +## +## @example +## v(1) * z^(N-1) + ... + v(N-1) * z + v(N). +## @end example +## @end ifnottex +## +## The number of roots returned and their value will be determined +## by the order and primitive polynomial of the Galois Field +## @end deftypefn + +function r = roots (v) + + if (nargin != 1) + print_usage (); + endif + + if (!isgalois (v)) + error ("roots: argument must be a galois variable"); + endif + + if (min (size (v)) > 1 || nargin != 1) + print_usage (); + endif + + v = reshape (v, 1, length (v)); + m = v.m; + prim_poly = v.prim_poly; + n = 2^m - 1; + poly = v; + nr = 0; + t = 0; + r = []; + + while (t <= n && length (poly) > 1) + [npoly, nrem] = deconv (poly, gf ([1, t], m, prim_poly)); + if (any (nrem)) + t = t + 1; + else + nr = nr + 1; + r(nr) = t; + poly = npoly; + endif + endwhile + + r = gf (r, m, prim_poly); + +endfunction + +%%Test input validation +%!error roots (gf (eye (3), 3)) diff --git a/inst/@galois/sqrt.m b/inst/@galois/sqrt.m new file mode 100644 index 0000000..7266849 --- /dev/null +++ b/inst/@galois/sqrt.m @@ -0,0 +1,27 @@ +## Copyright (C) 2011 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Loadable Function} {} sqrt (@var{x}) +## Compute the square root of @var{x}, element by element, in a Galois Field. +## @seealso{exp} +## @end deftypefn + +function varargout = sqrt (varargin) + + varargout = cell (1, max (1, nargout)); + [varargout{:}] = gsqrt (varargin{:}); + +endfunction diff --git a/inst/@galois/sum.m b/inst/@galois/sum.m new file mode 100644 index 0000000..c2a7b19 --- /dev/null +++ b/inst/@galois/sum.m @@ -0,0 +1,27 @@ +## Copyright (C) 2011 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Loadable Function} {} sum (@var{x}, @var{dim}) +## Sum of elements along dimension @var{dim} of Galois array. If @var{dim} +## is omitted, it defaults to 1 (column-wise sum). +## @end deftypefn + +function varargout = sum (varargin) + + varargout = cell (1, max (1, nargout)); + [varargout{:}] = gsum (varargin{:}); + +endfunction diff --git a/inst/@galois/sumsq.m b/inst/@galois/sumsq.m new file mode 100644 index 0000000..9215080 --- /dev/null +++ b/inst/@galois/sumsq.m @@ -0,0 +1,33 @@ +## Copyright (C) 2011 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Loadable Function} {} sumsq (@var{x}, @var{dim}) +## Sum of squares of elements along dimension @var{dim} of Galois array. +## If @var{dim} is omitted, it defaults to 1 (column-wise sum of squares). +## +## This function is equivalent to computing +## @example +## gsum (x .* conj (x), dim) +## @end example +## but it uses less memory. +## @end deftypefn + +function varargout = sumsq (varargin) + + varargout = cell (1, max (1, nargout)); + [varargout{:}] = gsumsq (varargin{:}); + +endfunction diff --git a/inst/ademodce.m b/inst/ademodce.m new file mode 100644 index 0000000..2b9190b --- /dev/null +++ b/inst/ademodce.m @@ -0,0 +1,191 @@ +## Copyright (C) 2003 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{y} =} ademodce (@var{x}, @var{Fs}, "amdsb-tc", offset) +## @deftypefnx {Function File} {@var{y} =} ademodce (@var{x}, @var{Fs}, "amdsb-tc/costas", offset) +## @deftypefnx {Function File} {@var{y} =} ademodce (@var{x}, @var{Fs}, "amdsb-sc") +## @deftypefnx {Function File} {@var{y} =} ademodce (@var{x}, @var{Fs}, "amdsb-sc/costas") +## @deftypefnx {Function File} {@var{y} =} ademodce (@var{x}, @var{Fs}, "amssb") +## @deftypefnx {Function File} {@var{y} =} ademodce (@var{x}, @var{Fs}, "qam") +## @deftypefnx {Function File} {@var{y} =} ademodce (@var{x}, @var{Fs}, "qam/cmplx") +## @deftypefnx {Function File} {@var{y} =} ademodce (@var{x}, @var{Fs}, "fm", @var{dev}) +## @deftypefnx {Function File} {@var{y} =} ademodce (@var{x}, @var{Fs}, "pm", @var{dev}) +## @deftypefnx {Function File} {@var{y} =} ademodce (@var{x}, [@var{Fs}, @var{iphs}], @dots{}) +## @deftypefnx {Function File} {@var{y} =} ademodce (@dots{}, @var{num}, @var{den}) +## +## Baseband demodulator for analog signals. The input signal is specified by +## @var{x}, its sampling frequency by @var{Fs} and the type of modulation +## by the third argument, @var{typ}. The default values of @var{Fs} is 1 and +## @var{typ} is "amdsb-tc". +## +## If the argument @var{Fs} is a two element vector, the first element +## represents the sampling rate and the second the initial phase. +## +## The different types of demodulations that are available are +## +## @table @asis +## @item "am" +## @itemx "amdsb-tc" +## Double-sideband with carrier +## @item "amdsb-tc/costas" +## Double-sideband with carrier and Costas phase locked loop +## @item "amdsb-sc" +## Double-sideband with suppressed carrier +## @item "amssb" +## Single-sideband with frequency domain Hilbert filtering +## @item "qam" +## Quadrature amplitude demodulation. In-phase in odd-columns and quadrature +## in even-columns +## @item "qam/cmplx" +## Quadrature amplitude demodulation with complex return value. +## @item "fm" +## Frequency demodulation +## @item "pm" +## Phase demodulation +## @end table +## +## Additional arguments are available for the demodulations "amdsb-tc", "fm", +## "pm". These arguments are +## +## @table @code +## @item offset +## The offset in the input signal for the transmitted carrier. +## @item dev +## The deviation of the phase and frequency modulation +## @end table +## +## It is possible to specify a low-pass filter, by the numerator @var{num} +## and denominator @var{den} that will be applied to the returned vector. +## +## @seealso{ademodce, dmodce} +## @end deftypefn + +function y = ademodce (x, Fs, typ, varargin) + + if (nargin < 1) + print_usage (); + elseif (nargin < 2) + Fs = 1; + typ = "am"; + elseif (nargin < 3) + typ = "am"; + endif + + if (isempty (Fs)) + Fs = 1; + iphs = 0; + elseif (isscalar (Fs)) + iphs = 0; + else + if ((max (size (Fs)) != 2) || (min (size (Fs)) != 1)) + error ("ademodce: FS must be a scalar or a 2-element vector"); + endif + Fs = Fs(1); + iphs = Fs(2); + endif + + ## Pass the optional arguments + dev = 1; + num = []; + den = []; + narg = 1; + if (!ischar (typ)) + error ("ademodce: demodulation type must be a string"); + elseif (strcmp (typ, "am") || strcmp (typ, "amdsb-tc")) + if (length (varargin) > 0) + offset = varargin{1}; + narg = narg + 1; + endif + elseif (strcmp (typ, "fm") || strcmp (typ, "pm")) + if (length (varargin) > 0) + dev = varargin{1}; + narg = narg + 1; + endif + endif + if (length (varargin) == narg) + error ("ademodce: must specify numerator and denominator of transfer function"); + elseif (length (varargin) == narg+1) + num = varargin{narg}; + den = varargin{narg+1}; + elseif (length (varargin) != narg - 1) + error ("ademodce: too many arguments"); + endif + + if (strcmp (typ, "am") || findstr (typ, "amdsb-tc")) + if (findstr (typ, "/costas")) + error ("ademodce: Costas phase locked loop not yet implemented"); + endif + y = real (x * exp (-1i * iphs)); + if (exist ("offset", "var")) + y = y - offset; + else + if (min (size (y)) == 1) + y = y - mean (y); + else + for i = 1:size (y, 2) + y(:,i) = y(:,i) - mean (y(:,i)); + endfor + endif + endif + elseif (strcmp (typ, "amdsb-sc")) + y = real (x * exp (-1i * iphs)); + elseif (findstr (typ, "amssb")) + if (findstr (typ, "/costas")) + error ("ademodce: Costas phase locked loop not yet implemented"); + endif + y = real (x * exp (-1i * iphs)); + elseif (strcmp (typ, "qam")) + y1 = x * exp (-1i * iphs); + y = zeros (size (y1, 1), 2*size (y1, 2)); + y(:,1:2:size (y, 2)) = real (y1); + y(:,2:2:size (y, 2)) = imag (y1); + elseif (strcmp (typ, "qam/cmplx")) + y = x * exp (-1i * iphs); + elseif (strcmp (typ, "pm")) + y = ( -1i * log (x) + iphs) / dev; + elseif (strcmp (typ, "fm")) + ## This can't work as it doesn't take into account the + ## phase wrapping in the modulation process. Therefore + ## we'll get some of the demodulated values in error, with + ## most of the values being correct.. + ## + ## Not sure the best approach to fixing this. Perhaps implement + ## a PLL with the ouput of the phase detector being the demodulated + ## signal... + warning ("ademodce: FM demodulation broken!!") + pm = Fs / dev / pi * ( - 1i * log (x) + iphs) + y = [pm(:,1), (pm(:,2:size (pm, 2)) - pm(:,1:size (pm, 2)-1))]; + else + error ("ademodce: unknown demodulation type '%s'", typ); + endif + + if (!isempty (num) && !isempty (dem)) + ## Low-pass filter the output + if (min (size (y)) == 1) + y = filter (num, den, y); + else + for i = 1:size (y, 2) + y(:,i) = filter (num, den, y(:,i)); + endfor + endif + endif + +endfunction + +%% Test input validation +%!error ademodce () +%!error ademodce (1, 2, "invalid") +%!error ademodce (1, 2, "am", 3, 4, 5, 6) diff --git a/inst/amdemod.m b/inst/amdemod.m new file mode 100644 index 0000000..fcfb429 --- /dev/null +++ b/inst/amdemod.m @@ -0,0 +1,95 @@ +## Copyright (C) 2021 The Octave Project Developers +## Copyright (C) 2007 Sylvain Pelissier +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{m} =} amdemod (@var{s}, @var{fc}, @var{fs}) +## Creates the AM demodulation of the signal @var{s} +## sampled at frequency @var{fs} with carrier frequency @var{fc}. +## +## Inputs: +## @itemize +## @item +## @var{s}: AM modulated signal +## +## @item +## @var{fc}: carrier frequency +## +## @item +## @var{fs}: sampling frequency +## @end itemize +## +## Output: +## @itemize +## @item +## @var{m}: AM demodulation of the signal +## @end itemize +## +## Demo +## @example +## demo amdemod +## @end example +## @seealso{ammod, fmmod, fmdemod} +## @end deftypefn + +function m = amdemod (s, fc, fs) + + if (nargin != 3) + print_usage (); + endif + + if (fs < 2 .* fc) + error ("amdemod: fs is too small must be at least 2 * fc") + endif + + l = length (s); + t = 0: 1 ./ fs: (l .- 1) ./ fs; + + e = s .* cos (2 .* pi .* fc .* t); + [b a] = butter (5, fc .* 2 ./ fs); + m = filtfilt (b, a, e) .* 2; + +endfunction + +## Test input validation +%!error amdemod () +%!error amdemod (1) +%!error amdemod (1, 2) +%!error amdemod (1, 2, 3, 4) + +%!error amdemod (pi/2, 100, 10) + +## https://stackoverflow.com/questions/21902462/amplitude-modulation-using-builtin-octave-functions +%!demo +%! #Parameters +%! Fs = 44100; +%! T = 1; +%! Fc = 15000; +%! Fm = 10; + +%! #Low-pass filter design +%! [num,den] = butter(10,1.2*Fc/Fs); + +%! #Signals +%! t = 0:1/Fs:T; +%! x = cos(2*pi*Fm*t); +%! y = ammod(x,Fc,Fs); +%! z = amdemod(y,Fc,Fs); + +%! #Plot +%! figure('Name','AM Modulation'); +%! subplot(3,1,1); plot(t,x); title('Modulating signal'); +%! subplot(3,1,2); plot(t,y); title('Modulated signal'); +%! subplot(3,1,3); plot(t,z); title('Demodulated signal'); \ No newline at end of file diff --git a/inst/ammod.m b/inst/ammod.m new file mode 100644 index 0000000..2999fd1 --- /dev/null +++ b/inst/ammod.m @@ -0,0 +1,89 @@ +## Copyright (C) 2021 The Octave Project Developers +## Copyright (C) 2007 Sylvain Pelissier +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{y} =} ammod (@var{x}, @var{fc}, @var{fs}) +## Creates the AM modulation of the amplitude signal @var{x} +## with carrier frequency @var{fc}. +## +## Inputs: +## @itemize +## @item +## @var{x}: amplitude message signal +## +## @item +## @var{fc}: carrier frequency +## +## @item +## @var{fs}: sampling frequency +## @end itemize +## +## Output: +## @itemize +## @var{y}: The AM modulation of @var{x} +## @end itemize +## Demo +## @example +## demo ammod +## @end example +## @seealso{amdemod, fmmod, fmdemod} +## @end deftypefn + +function y = ammod (x, fc, fs) + + if (nargin != 3) + print_usage (); + endif + + if (fs < 2 .* fc) + error ("ammod: fs is too small must be at least 2 * fc") + endif + + l = length (x); + t = 0: 1 ./ fs: (l .- 1) ./ fs; + y = x .* cos (2 .* pi .* fc .* t); + +endfunction + +## Test input validation +%!error ammod () +%!error ammod (1) +%!error ammod (1, 2) +%!error ammod (1, 2, 3, 4) + +%!error ammod (pi/2, 100, 10) + +## https://www.geeksforgeeks.org/amplitude-modulation-using-matlab/ +%!demo +%! ## carrier Frequency +%! fc = 200; +%! +%! ## sampling frequency +%! fs= 4000; +%! +%! ## time Duration +%! t = (0 : 1 ./ fs : 1); +%! +%! ## sine Wave with time duration of 't' +%! x = sin (2 .* pi .* t); +%! +%! ## Amplitude Modulation +%! y = ammod (x, fc, fs); +%! +%! plot(y); +%! title('Amplitude Modulation'); +%! xlabel('Time(sec)'); +%! ylabel('Amplitude'); diff --git a/inst/amodce.m b/inst/amodce.m new file mode 100644 index 0000000..17c3a17 --- /dev/null +++ b/inst/amodce.m @@ -0,0 +1,176 @@ +## Copyright (C) 2003 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{y} =} amodce (@var{x}, @var{Fs}, "amdsb-tc", offset) +## @deftypefnx {Function File} {@var{y} =} amodce (@var{x}, @var{Fs}, "amdsb-sc") +## @deftypefnx {Function File} {@var{y} =} amodce (@var{x}, @var{Fs}, "amssb") +## @deftypefnx {Function File} {@var{y} =} amodce (@var{x}, @var{Fs}, "amssb/time", @var{num}, @var{den}) +## @deftypefnx {Function File} {@var{y} =} amodce (@var{x}, @var{Fs}, "qam") +## @deftypefnx {Function File} {@var{y} =} amodce (@var{x}, @var{Fs}, "fm", @var{dev}) +## @deftypefnx {Function File} {@var{y} =} amodce (@var{x}, @var{Fs}, "pm", @var{dev}) +## @deftypefnx {Function File} {@var{y} =} amodce (@var{x}, [@var{Fs}, @var{iphs}], @dots{}) +## +## Baseband modulator for analog signals. The input signal is specified by +## @var{x}, its sampling frequency by @var{Fs} and the type of modulation +## by the third argument, @var{typ}. The default values of @var{Fs} is 1 and +## @var{typ} is "amdsb-tc". +## +## If the argument @var{Fs} is a two element vector, the first element +## represents the sampling rate and the second the initial phase. +## +## The different types of modulations that are available are +## +## @table @asis +## @item "am" +## @itemx "amdsb-tc" +## Double-sideband with carrier +## @item "amdsb-sc" +## Double-sideband with suppressed carrier +## @item "amssb" +## Single-sideband with frequency domain Hilbert filtering +## @item "amssb/time" +## Single-sideband with time domain filtering. Hilbert filter is used by +## default, but the filter can be specified +## @item "qam" +## Quadrature amplitude modulation +## @item "fm" +## Frequency modulation +## @item "pm" +## Phase modulation +## @end table +## +## Additional arguments are available for the modulations "amdsb-tc", "fm", +## "pm" and "amssb/time". These arguments are +## +## @table @code +## @item offset +## The offset in the input signal for the transmitted carrier. +## @item dev +## The deviation of the phase and frequency modulation +## @item num +## @itemx den +## The numerator and denominator of the filter transfer function for the +## time domain filtering of the SSB modulation +## @end table +## +## @seealso{ademodce, dmodce} +## @end deftypefn + +function y = amodce (x, Fs, typ, varargin) + + if (nargin < 1) + print_usage (); + elseif (nargin < 2) + Fs = 1; + typ = "am"; + elseif (nargin < 3) + typ = "am"; + endif + + if (isempty (Fs)) + Fs = 1; + iphs = 0; + elseif (isscalar (Fs)) + iphs = 0; + else + if (max (size (Fs)) != 2 || min (size (Fs)) != 1) + error ("amodce: FS must be a scalar or a 2-element vector"); + endif + Fs = Fs(1); + iphs = Fs(2); + endif + + ## Pass the optional arguments + offset = min (x(:)); + dev = 1; + num = []; + den = []; + narg = 1; + if (!ischar (typ)) + error ("amodce: modulation type must be a string"); + elseif (strcmp (typ, "am") || strcmp (typ, "amdsb-tc")) + if (length (varargin) > 0) + offset = varargin{1}; + narg = narg + 1; + endif + elseif (strcmp (typ, "fm") || strcmp (typ, "pm")) + if (length (varargin) > 0) + dev = varargin{1}; + narg = narg + 1; + endif + endif + if (length (varargin) == narg) + error ("amodce: must specify numerator and denominator of transfer function"); + elseif (length (varargin) == narg + 1) + num = varargin{narg}; + den = varargin{narg+1}; + elseif (length (varargin) != narg - 1) + error ("amodce: too many arguments"); + endif + + if (strcmp (typ, "am") || strcmp (typ, "amdsb-tc")) + y = (x + offset) * exp (1i * iphs); + elseif (strcmp (typ, "amdsb-sc")) + y = x * exp (1i * iphs); + elseif (strcmp (typ, "amssb")) + if (!isreal (x)) + error ("amodce: SSB modulated signal must be real"); + endif + ## Damn, must treat Hilbert transform row-by-row!!! + y = zeros (size (x)); + for i = 1:size (x, 2) + y(:,i) = hilbert (x(:,i)) * exp (1i * iphs); + endfor + elseif (strcmp (typ, "amssb/time")) + if (isempty (num) || isempty (dem)) + error ("amodce: Hilbert transform in time domain not yet implemented"); + endif + y = zeros (size (x)); + for i = 1:size (x, 2) + y(:,i) = filter (num, den, x(:,i)); + y(:,i) = (x(:,i) + 1i*y(:,i)) * exp (1i * iphs); + endfor + elseif (strcmp (typ, "qam")) + if (isreal (x)) + xc = columns (x); + if (xc/2 != fix (xc/2)) + error ("amodce: QAM modulation must have an even number of columns for real signals"); + endif + y = (x(:,1:2:xc) + 1i * x(:,2:2:xc)); + else + y = x; + endif + y = y * exp (1i * iphs); + elseif (strcmp (typ, "pm")) + y = exp (1i * (dev*x + iphs)); + elseif (strcmp (typ, "fm")) + ## To convert to PM signal, need to evaluate + ## p(t) = \int_0^t dev * x(T) dT + ## As x(t) is discrete and not a function, the only way to perform the + ## above integration is with Simpson's rule. Note \Delta T = 2 * pi / Fs. + pm = pi / Fs * dev * (cumsum ([zeros(1, size (x, 2)); x(1:size (x, 1) - 1,:)]) ... + + cumsum (x)); + y = exp (1i * (pm + iphs)); + else + error ("amodce: unknown modulation specified '%s'", typ); + endif + +endfunction + +%% Test input validation +%!error amodce () +%!error amodce (1, 2, "invalid") +%!error amodce (1, 2, "am", 3, 4, 5, 6) diff --git a/inst/apkconst.m b/inst/apkconst.m new file mode 100644 index 0000000..3773ef3 --- /dev/null +++ b/inst/apkconst.m @@ -0,0 +1,147 @@ +## Copyright (C) 2003 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} apkconst (@var{nsig}) +## @deftypefnx {Function File} {} apkconst (@var{nsig}, @var{amp}) +## @deftypefnx {Function File} {} apkconst (@var{nsig}, @var{amp}, @var{phs}) +## @deftypefnx {Function File} {} apkconst (@dots{}, "n") +## @deftypefnx {Function File} {} apkconst (@dots{}, @var{str}) +## @deftypefnx {Function File} {@var{y} =} apkconst (@dots{}) +## +## Plots a ASK/PSK signal constellation. Argument @var{nsig} is a real vector +## whose length determines the number of ASK radii in the constellation. +## The values of vector @var{nsig} determine the number of points in each +## ASK radii. +## +## By default the radii of each ASK modulated level is given by the index of +## @var{nsig}. The amplitudes can be defined explicitly in the variable +## @var{amp}, which is a vector of the same length as @var{nsig}. +## +## By default the first point in each ASK radii has zero phase, and following +## points are coding in an anti-clockwise manner. If @var{phs} is defined then +## it is a vector of the same length as @var{nsig} defining the initial phase +## in each ASK radii. +## +## In addition @code{apkconst} takes two string arguments "n" and @var{str}. +## If the string "n" is included in the arguments, then a number is printed +## next to each constellation point giving the symbol value that would be +## mapped to this point by the @code{modmap} function. The argument @var{str} +## is a plot style string (example "r+") and determines the default gnuplot +## point style to use for plot points in the constellation. +## +## If @code{apkconst} is called with a return argument, then no plot is +## created. However the return value is a vector giving the in-phase and +## quadrature values of the symbols in the constellation. +## @seealso{dmod, ddemod, modmap, demodmap} +## @end deftypefn + +function yout = apkconst (varargin) + + if (nargin < 1 || nargin > 5) + print_usage (); + endif + + numargs = 0; + printnums = 0; + fmt = "+r"; + amp = []; + phs = []; + + for i = 1:length (varargin) + arg = varargin{i}; + if (ischar (arg)) + if (strcmp (arg, "n")) + try + text (); + printnums = 1; + catch + printnums = 0; + end_try_catch + else + fmt = arg; + endif + else + numargs++; + switch (numargs) + case 1 + nsig = arg; + case 2 + amp = arg; + case 3 + phs = arg; + otherwise + error ("apkconst: too many numerical arguments"); + endswitch + endif + endfor + + if (numargs < 1) + error ("apkconst: must have at least one vector argument"); + endif + + if (isempty (amp)) + amp = 1:length (nsig); + endif + + if (isempty (phs)) + phs = zeros (size (amp)); + endif + + if (!isvector (nsig) || !isvector (amp) || !isvector (phs) || ... + (length (nsig) != length (amp)) || (length (nsig) != length (phs))) + error ("apkconst: NSIG, AMP, and PHS must be vectors of common size"); + endif + + if (length (nsig) == 0) + error ("apkconst: NSIG must have non-zero length"); + endif + + y = []; + for i = 1:length (nsig) + if (nsig(i) < 1) + error ("apkconst: NSIG must have at least one point in ASK radii"); + endif + y = [y; amp(i) * [cos(2*pi*[0:nsig(i)-1]'/nsig(i) + phs(i)) + ... + 1i*sin(2*pi*[0:nsig(i)-1]'/nsig(i) + phs(i))]]; + endfor + + if (nargout == 0) + r = [0:0.02:2]'*pi; + x0 = cos (r) * amp; + y0 = sin (r) * amp; + plot (x0, y0, "b"); + yy = [real(y), imag(y)]; + hold on; + if (printnums) + xd = 0.05 * max (real (y)); + for i = 1:length (y) + text (real (y(i)) + xd, imag (y(i)), num2str (i-1)); + endfor + endif + plot (real (y), imag (y), fmt); + + title ("ASK/PSK Constellation"); + xlabel ("In-phase"); + ylabel ("Quadrature"); + else + yout = y; + endif + +endfunction + +%% Test input validation +%!error apkconst () +%!error apkconst (1, 2, 3, 4) diff --git a/inst/awgn.m b/inst/awgn.m new file mode 100644 index 0000000..a88d8d5 --- /dev/null +++ b/inst/awgn.m @@ -0,0 +1,145 @@ +## Copyright (C) 2002 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{y} =} awgn (@var{x}, @var{snr}) +## @deftypefnx {Function File} {@var{y} =} awgn (@var{x}, @var{snr}, @var{pwr}) +## @deftypefnx {Function File} {@var{y} =} awgn (@var{x}, @var{snr}, @var{pwr}, @var{seed}) +## @deftypefnx {Function File} {@var{y} =} awgn (@dots{}, @var{type}) +## +## Add white Gaussian noise to a voltage signal. +## +## The input @var{x} is assumed to be a real or complex voltage signal. The +## returned value @var{y} will be the same form and size as @var{x} but with +## Gaussian noise added. Unless the power is specified in @var{pwr}, the +## signal power is assumed to be 0dBW, and the noise of @var{snr} dB will be +## added with respect to this. If @var{pwr} is a numeric value then the signal +## @var{x} is assumed to be @var{pwr} dBW, otherwise if @var{pwr} is +## "measured", then the power in the signal will be measured and the noise +## added relative to this measured power. +## +## If @var{seed} is specified, then the random number generator seed is +## initialized with this value +## +## By default the @var{snr} and @var{pwr} are assumed to be in dB and dBW +## respectively. This default behavior can be chosen with @var{type} +## set to "dB". In the case where @var{type} is set to "linear", @var{pwr} +## is assumed to be in Watts and @var{snr} is a ratio. +## @seealso{randn, wgn} +## @end deftypefn + +function y = awgn (x, snr, varargin) + + if (nargin < 2 || nargin > 5) + print_usage (); + endif + + [m, n] = size (x); + if (isreal (x)) + out = "real"; + else + out = "complex"; + endif + + p = 0; + seed = []; + type = "dB"; + meas = 0; + narg = 0; + + for i = 1:length (varargin) + arg = varargin{i}; + if (ischar (arg)) + if (strcmp (arg, "measured")) + meas = 1; + elseif (strcmp (arg, "dB")) + type = "dB"; + elseif (strcmp (arg, "linear")) + type = "linear"; + else + error ("awgn: invalid argument '%s'", arg); + endif + else + narg++; + switch (narg) + case 1 + p = arg; + case 2 + seed = arg; + otherwise + error ("awgn: too many arguments"); + endswitch + endif + endfor + + if (isempty (p)) + p = 0; + endif + + if (!isempty (seed)) + if (! (isscalar (seed) && isreal (seed) && seed >= 0 && seed == fix (seed))) + error ("awgn: random SEED must be an integer"); + endif + endif + + if (!isscalar (p) || !isreal (p)) + error ("awgn: PWR must be a scalar"); + endif + if (strcmp (type, "linear") && p < 0) + error ("awgn: PWR must be a non-negative scalar for TYPE \"linear\""); + endif + + if (!isscalar (snr) || !isreal (snr)) + error ("awgn: SNR must be a scalar"); + endif + if (strcmp (type, "linear") && snr < 0) + error ("awgn: SNR must be a non-negative scalar for TYPE \"linear\""); + endif + + if (!isempty (seed)) + randn ("state", seed); + endif + + if (meas == 1) + p = sum (abs (x(:)) .^ 2) / length (x(:)); + if (strcmp (type, "dB")) + p = 10 * log10 (p); + endif + endif + + if (strcmp (type, "linear")) + np = p / snr; + else + np = p - snr; + endif + + y = x + wgn (m, n, np, 1, seed, type, out); + +endfunction + +%!shared x, y, noisy +%! x = [0:0.01:2*pi]; y = sin (x); +%! noisy = awgn (y, 20, "dB", "measured"); + +## Test of noisy is pretty arbitrary, but should pickup most errors +%!assert (isreal (noisy)); +%!assert (iscomplex (awgn (y + 1i, 20, "dB", "measured"))); +%!assert (size (y) == size (noisy)) +%!assert (abs (10*log10 (mean (y.^2)/mean ((y-noisy).^ 2)) - 20) < 1); + +%% Test input validation +%!error awgn (); +%!error awgn (1); +%!error awgn (1, 1, 1, 1, 1); diff --git a/inst/bchpoly.m b/inst/bchpoly.m new file mode 100644 index 0000000..e014b5f --- /dev/null +++ b/inst/bchpoly.m @@ -0,0 +1,239 @@ +## Copyright (C) 2003 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{p} =} bchpoly () +## @deftypefnx {Function File} {@var{p} =} bchpoly (@var{n}) +## @deftypefnx {Function File} {@var{p} =} bchpoly (@var{n}, @var{k}) +## @deftypefnx {Function File} {@var{p} =} bchpoly (@var{prim}, @var{k}) +## @deftypefnx {Function File} {@var{p} =} bchpoly (@var{n}, @var{k}, @var{prim}) +## @deftypefnx {Function File} {@var{p} =} bchpoly (@dots{}, @var{probe}) +## @deftypefnx {Function File} {[@var{p}, @var{f}] =} bchpoly (@dots{}) +## @deftypefnx {Function File} {[@var{p}, @var{f}, @var{c}] =} bchpoly (@dots{}) +## @deftypefnx {Function File} {[@var{p}, @var{f}, @var{c}, @var{par}] =} bchpoly (@dots{}) +## @deftypefnx {Function File} {[@var{p}, @var{f}, @var{c}, @var{par}, @var{t}] =} bchpoly (@dots{}) +## +## Calculates the generator polynomials for a BCH coder. Called with no input +## arguments @code{bchpoly} returns a list of all of the valid BCH codes for +## the codeword length 7, 15, 31, 63, 127, 255 and 511. A three column matrix +## is returned with each row representing a separate valid BCH code. The first +## column is the codeword length, the second the message length and the third +## the error correction capability of the code. +## +## Called with a single input argument, @code{bchpoly} returns the valid BCH +## codes for the specified codeword length @var{n}. The output format is the +## same as above. +## +## When called with two or more arguments, @code{bchpoly} calculates the +## generator polynomial of a particular BCH code. The generator polynomial +## is returned in @var{p} as a vector representation of a polynomial in +## GF(2). The terms of the polynomial are listed least-significant term +## first. +## +## The desired BCH code can be specified by its codeword length @var{n} +## and its message length @var{k}. Alternatively, the primitive polynomial +## over which to calculate the polynomial can be specified as @var{prim}. +## If a vector representation of the primitive polynomial is given, then +## @var{prim} can be specified as the first argument of two arguments, +## or as the third argument. However, if an integer representation of the +## primitive polynomial is used, then the primitive polynomial must be +## specified as the third argument. +## +## When called with two or more arguments, @code{bchpoly} can also return the +## factors @var{f} of the generator polynomial @var{p}, the cyclotomic coset +## for the Galois field over which the BCH code is calculated, the parity +## check matrix @var{par} and the error correction capability @var{t}. It +## should be noted that the parity check matrix is calculated with +## @code{cyclgen} and limitations in this function means that the parity +## check matrix is only available for codeword length up to 63. For +## codeword length longer than this @var{par} returns an empty matrix. +## +## With a string argument @var{probe} defined, the action of @code{bchpoly} +## is to calculate the error correcting capability of the BCH code defined +## by @var{n}, @var{k} and @var{prim} and return it in @var{p}. This is +## similar to a call to @code{bchpoly} with zero or one argument, except that +## only a single code is checked. Any string value for @var{probe} will +## force this action. +## +## In general the codeword length @var{n} can be expressed as +## @code{2^@var{m}-1}, where @var{m} is an integer. However, if +## [@var{n},@var{k}] is a valid BCH code, then a shortened BCH code of +## the form [@var{n}-@var{x},@var{k}-@var{x}] can be created with the +## same generator polynomial +## +## @seealso{cyclpoly, encode, decode, cosets} +## @end deftypefn + +function [p, f, c, par, t] = bchpoly (nn, k, varargin) + + if (nargin < 0 || nargin > 4) + print_usage (); + endif + + probe = 0; + prim = 0; ## Set to zero to use default primitive polynomial + if (nargin == 0) + m = [3:9]; + n = 2.^m - 1; + nn = n; + elseif (isscalar (nn)) + m = ceil (log2 (nn+1)); + n = 2.^m - 1; + if (! (n == fix (n) && n >= 7 && m == fix (m))) + error ("bchpoly: N must be a integer greater than 3"); + endif + else + prim = bi2de (n); + if (!isprimitive (prim)) + error ("bchpoly: PRIM must be a primitive polynomial of GF(2^M)"); + endif + m = length (n) - 1; + n = 2^m - 1; + endif + + if (nargin > 1 && ! (isscalar (k) && k == fix (k) && k <= n)) + error ("bchpoly: K must be an integer less than N"); + endif + + for i = 1:length (varargin) + arg = varargin{i}; + if (ischar (arg)) + probe = 1; + if (nargout > 1) + error ("bchpoly: only one output argument allowed when probing valid codes"); + endif + else + if (prim != 0) + error ("bchpoly: primitive polynomial already defined"); + endif + prim = arg; + if (!isscalar (prim)) + prim = bi2de (prim); + endif + if (! (prim == fix (prim) && prim >= 2^m && prim <= 2^(m+1) + && isprimitive (prim))) + error ("bchpoly: PRIM must be a primitive polynomial of GF(2^M)"); + endif + endif + endfor + + ## Am I using the right algo to calculate the correction capability? + if (nargin < 2) + if (nargout > 1) + error ("bchpoly: only one output argument allowed when probing valid codes"); + endif + + p = []; + for ni = 1:length (n) + c = cosets (m(ni), prim); + nc = length (c); + fc = zeros (1, nc); + f = []; + + for t = 1:floor (n(ni)/2) + for i = 1:nc + if (fc(i) != 1) + cl = log (c{i}); + for j = 2*(t-1)+1:2*t + if (find (cl == j)) + f = [f, c{i}.x]; + fc(i) = 1; + break; + endif + endfor + endif + endfor + + k = nn(ni) - length (f); + if (k < 2) + break; + endif + + if (!isempty (p) && (k == p(size (p, 1),2))) + p(size (p, 1),:) = [nn(ni), k, t]; + else + p = [p; [nn(ni), k, t]]; + endif + endfor + endfor + else + c = cosets (m, prim); + nc = length (c); + fc = zeros (1, nc); + f = []; + fl = 0; + f0 = []; + f1 = []; + t = 0; + do + t++; + f0 = f1; + for i = 1:nc + if (fc(i) != 1) + cl = log (c{i}); + for j = 2*(t-1)+1:2*t + if (find (cl == j)) + f1 = [f1, c{i}.x]; + fc(i) = 1; + ptmp = gf ([c{i}(1), 1], m, prim); + for l = 2:length (c{i}) + ptmp = conv (ptmp, [c{i}(l), 1]); + endfor + f = [f; [ptmp.x, zeros(1, m - length (ptmp) + 1)]]; + fl = fl + length (ptmp); + break; + endif + endfor + endif + endfor + until (length (f1) > nn - k) + t--; + + if (nn - length (f0) != k) + error ("bchpoly: could not find valid generator polynomial for parameters"); + endif + + if (probe) + p = [nn, k, t]; + else + + ## Have to delete a line from the list of minimum polynomials + ## since we've gone one past in calculating f1 above to be + ## sure or the error correcting capability + f = f(1:size (f, 1) - 1,:); + + p = gf ([f0(1), 1], m, prim); + for i = 2:length (f0) + p = conv (p, [f0(i), 1]); + endfor + p = p.x; + + if (nargout > 3) + if (n > 64) + warning ("bchpoly: could not create parity matrix"); + par = []; + else + par = cyclgen (n, p); + endif + endif + endif + endif + +endfunction + +%% Test input validation +%!error bchpoly (1) +%!error bchpoly (1, 2, 3, 4, 5) +%!error bchpoly (5, 10) diff --git a/inst/berconfint.m b/inst/berconfint.m new file mode 100644 index 0000000..df891ee --- /dev/null +++ b/inst/berconfint.m @@ -0,0 +1,66 @@ +## Copyright (C) 2020 Pedro Rodriguez Torija +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{ber} =} berconfint (@var{r}, @var{n}) +## @deftypefnx {Function File} {[@var{ber}, @var{interval}] =} berconfint (@var{r}, @var{n}) +## @deftypefnx {Function File} {[@var{ber}, @var{interval}] =} berconfint (@var{r}, @var{n}, @var{level}) +## +## Returns Bit Error Rate, @var{ber}, and confidence interval, @var{interval}, for +## the number of errors @var{r} and number of transmitted bits @var{n} with a +## confidence level of @var{level}. By default @var{level} is 0.95. +## +## The confidence interval is the Wilson one (without continuity correction) for a proportion. By contrast, Matlab appears to return the Clopper–Pearson confidence interval. +## +## Reference: +## Robert G. Newcombe (1998), "Two‐sided confidence intervals for the single proportion: comparison of seven methods", Statistics in Medicine 17(8):857-872. +## @end deftypefn + + +function [ber, conf_inter] = berconfint(r,n,level) + + switch (nargin) + case 2 + level = 0.95; + case 3 + level = level; + otherwise + print_usage (); + endswitch + + ber = r / n; + + if isargout (2) + d = - sqrt (2) * erfcinv (1 + level); + d2 = d^2; + y = 2 * (n + d2); + x = ( 2 * r + d2 ) / y; + z = sqrt( (4 * r * n + n * d2 - 4 * r^2) / n); + conf_inter = x + [-1 1]*(d / y * z); + endif + +endfunction + +%!assert (berconfint (1, 2), 0.5) +%!assert (berconfint (10, 200, 0.98), 0.05) + +%!test +%! [ber, conf_inter] = berconfint(100, 1E6, 0.95); +%! assert (ber, 1E-4) +%! assert (conf_inter, [8.222786e-05 1.216128e-04], 1E-10) #values are from prop.test(x=100,n=1E6,correct=FALSE) in R + +%% Test input validation +%!error berconfint () +%!error berconfint (1, 2, 3, 4) diff --git a/inst/bi2de.m b/inst/bi2de.m new file mode 100644 index 0000000..f4d74f4 --- /dev/null +++ b/inst/bi2de.m @@ -0,0 +1,96 @@ +## Copyright (C) 2001 Laurent Mazet +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{d} =} bi2de (@var{b}) +## @deftypefnx {Function File} {@var{d} =} bi2de (@var{b}, @var{f}) +## @deftypefnx {Function File} {@var{d} =} bi2de (@var{b}, @var{p}) +## @deftypefnx {Function File} {@var{d} =} bi2de (@var{b}, @var{p}, @var{f}) +## +## Convert bit matrix to a vector of integers +## +## Each row of the matrix @var{b} is treated as a single integer represented +## in binary form. The elements of @var{b}, must therefore be '0' or '1' +## +## If @var{p} is defined then it is treated as the base of the decomposition +## and the elements of @var{b} must then lie between '0' and 'p-1'. +## +## The variable @var{f} defines whether the first or last element of @var{b} +## is considered to be the most-significant. Valid values of @var{f} are +## "right-msb" or "left-msb". By default @var{f} is "right-msb". +## +## @seealso{de2bi} +## @end deftypefn + +function d = bi2de (b, p, f) + + switch (nargin) + case 1 + p = 2; + f = "right-msb"; + case 2 + if (ischar (p)) + f = p; + p = 2; + else + f = "right-msb"; + endif + case 3 + if (ischar (p)) + tmp = f; + f = p; + p = tmp; + endif + otherwise + print_usage (); + endswitch + + if (! (all (b(:) == fix (b(:))) && all (b(:) >= 0) && all (b(:) < p))) + error ("bi2de: all elements of B must be integers in the range [0,P-1]"); + endif + + if (strcmp (f, "left-msb")) + b = b(:,size (b, 2):-1:1); + elseif (!strcmp (f, "right-msb")) + error ("bi2de: invalid option '%s'", f); + endif + + if (length (b) == 0) + d = []; + else + d = b * (p .^ [0:(columns (b) - 1)]'); + endif + +endfunction + +%!shared x +%! x = randi ([0 1], 100, 16); +%!assert (bi2de (0), 0) +%!assert (bi2de (1), 1) +%!assert (bi2de (ones (1, 8)), 255) +%!assert (bi2de ([7 7 7 7], 8), 4095) +%!assert (size (bi2de (x)), [100 1]) +%!assert (bi2de (x, "right-msb"), bi2de (x)) +%!assert (bi2de (x, "left-msb"), bi2de (fliplr (x))) + +%% Test input validation +%!error bi2de () +%!error bi2de (1, 2, 3, 4) +%!error bi2de (1, 2, 3) +%!error bi2de (1, 2, "invalid") +%!error bi2de (0.1) +%!error bi2de (-1) +%!error bi2de (2) +%!error bi2de (7, 6) diff --git a/inst/bin2gray.m b/inst/bin2gray.m new file mode 100644 index 0000000..e69ab44 --- /dev/null +++ b/inst/bin2gray.m @@ -0,0 +1,168 @@ +## Copyright (C) 2021 The Octave Project Developers +## Copyright (C) 2016 Òscar Monerris Belda +## +## This program is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or +## (at your option) any later version. +## +## This program 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 General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program. If not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {[@var{y}, @var{mapping}] =} bin2gray (@var{x}, @var{type}, @var{M}) +## Creates a Gray encoded data @var{y} with the same size as input @var{x} +## +## Input: +## @itemize +## @item @var{x} Binary matrix data +## +## @item @var{type}: The modulation type +## choices available:'qam', 'pam','psk','dpsk', and 'fsk' +## +## @item @var{M}: The modualtion order must be a power of 2 +## @end itemize +## +## Output: +## @itemize +## @item @var{y}: The gray data of the @var{x} data. +## @item @var{mapping}: This provides the gray labesfor the given modulation. +## @end itemize +## +## Example +## @example +## y = bin2gray ([0:3], 'qam', 16) +## y = +## +## 0 +## 1 +## 3 +## 2 +## @end example +## +## Example with matrix +## @example +## y = bin2gray ([0:3; 12:15], 'qam', 16) +## y = +## +## 0 1 3 2 +## 8 9 11 10 +## @end example +## @seealso{qammod} +## @end deftypefn + +function [y, mapping] = bin2gray (x, type, M) + +if (nargin < 3) + print_usage(); +endif + +if (~isnumeric (M)) + error('bin2gray:: M must be an integer power of 2') +endif + +if (M < 1) + error('bin2gray:: M must be an integer power of 2') +endif + +if (fix (log2 (M)) ~= log2 (M)) + error('bin2gray:: M must be an integer power of 2') +endif + +if (max (x) > M - 1 || min (x) < 0) + error('bin2gray:: x array out of [0,M-1] range') +endif + + + +switch lower (type) + + case 'qam' + # Two dimensional modulations + + if (mod (nextpow2 (M), 2) == 0) + # Number of elements in the I and Q axis + nbits = nextpow2 (M); + nI = sqrt (M); + + # Split in two the number of bits + data1D = (0: nI - 1)'; + mapping1D = bitxor (data1D, bitshift (data1D, -1)); + # Gray code half of the bytes + bin1D = de2bi (mapping1D, nbits / 2); + + mapping = zeros (M, 1); + for id=1: nI + mapping((1 + nI * (id - 1)): nI * id) = bi2de ([bin1D ones(nI, 1) * bin1D(id, :)]); + endfor + + # Build the constallation - detailed code + # for id=0:M-1 + # idi = floor(id/nI)+1; + # idq = mod(id,nI)+1; + # mapping(id+1) = bi2de([bin1D(idq,:) bin1D(idi,:)]); + #endfor + + else + if (M == 8) + mapping = []; + elseif (M == 32) + mapping = []; + else + error('bin2gray:: log2(M) = 2*n+1 for n>2 is not implemented') + endif + endif + + case {'pam','psk','dpsk','fsk'} + + # One dimensional modulation + IQ = (0: M - 1)'; + mapping = bitxor (IQ, bitshift (IQ, -1)); + + otherwise + error('bin2gray:: type is not valid') +endswitch + +y = mapping (x + 1); + +endfunction + +%% Test input validation +%!error bin2gray () +%!error bin2gray (1) +%!error bin2gray (1, 2) +%!error bin2gray ([0:10], 'qam', 32) +%!error bin2gray ([0:3], 'qam', 15) + +%!test +%! assert (bin2gray ([0:3 12:15], 'qam', 16), [0 1 3 2 8 9 11 10]'); + +%!test +%! assert (bin2gray (0:3, 'psk', 16), [0 1 3 2]'); + +## Understanding the QAM gray coding +# +# For a square constellation the MSB (nbits/2) +# remain constant for the whole Q range and the +# Q range is enconded using a 1D gray coding +# but, at the same time, the I axis is coded +# using a standard 1D gray sequence keeping +# this value constant for all the Q's. +# +# -3 -1 +1 +3 +# | +#+3 00|10 01|10 | 11|10 10|10 -> Gray code the MSB +# | +#+1 00|11 01|11 | 11|11 10|11 +#-----------------|------------------ -> I axis +#-1 00|01 01|01 | 11|01 10|01 +# | +#-3 00|00 01|00 | 11|00 10|00 +# | +# v +# Q axis \ No newline at end of file diff --git a/inst/biterr.m b/inst/biterr.m new file mode 100644 index 0000000..44de527 --- /dev/null +++ b/inst/biterr.m @@ -0,0 +1,176 @@ +## Copyright (C) 2003 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {[@var{num}, @var{rate}] =} biterr (@var{a}, @var{b}) +## @deftypefnx {Function File} {[@var{num}, @var{rate}] =} biterr (@dots{}, @var{k}) +## @deftypefnx {Function File} {[@var{num}, @var{rate}] =} biterr (@dots{}, @var{flag}) +## @deftypefnx {Function File} {[@var{num}, @var{rate} @var{ind}] =} biterr (@dots{}) +## +## Compares two matrices and returns the number of bit errors and the bit +## error rate. The binary representations of the variables @var{a} and +## @var{b} are treated and @var{a} and @var{b} can be either: +## +## @table @asis +## @item Both matrices +## In this case both matrices must be the same size and then by default the +## return values @var{num} and @var{rate} are the overall number of bit +## errors and the overall bit error rate. +## @item One column vector +## In this case the column vector is used for bit error comparison column-wise +## with the matrix. The returned values @var{num} and @var{rate} are then +## row vectors containing the number of bit errors and the bit error rate for +## each of the column-wise comparisons. The number of rows in the matrix +## must be the same as the length of the column vector +## @item One row vector +## In this case the row vector is used for bit error comparison row-wise +## with the matrix. The returned values @var{num} and @var{rate} are then +## column vectors containing the number of bit errors and the bit error rate +## for each of the row-wise comparisons. The number of columns in the matrix +## must be the same as the length of the row vector +## @end table +## +## This behavior can be overridden with the variable @var{flag}. @var{flag} +## can take the value "column-wise", "row-wise" or "overall". A column-wise +## comparison is not possible with a row vector and visa-versa. +## +## By default the number of bits in each symbol is assumed to be give by the +## number required to represent the maximum value of @var{a} and @var{b}. +## The number of bits to represent a symbol can be overridden by the variable +## @var{k}. +## @end deftypefn + +function [num, rate, ind] = biterr (a, b, varargin) + + if (nargin < 2 || nargin > 4) + print_usage (); + endif + + if (ndims (a) > 2 || ndims (b) > 2) + error ("biterr: A and B must not have more than 2 dimensions"); + endif + + if (! (!any (isinf (a(:))) && !any (isnan (a(:))) && all (isreal (a(:))) + && all (a(:) == fix (a(:))) && all (a(:) >= 0))) + error ("biterr: all elements of A must be non-negative integers"); + endif + + if (! (!any (isinf (b(:))) && !any (isnan (b(:))) && all (isreal (b(:))) + && all (b(:) == fix (b(:))) && all (b(:) >= 0))) + error ("biterr: all elements of B must be non-negative integers"); + endif + + [ar, ac] = size (a); + [br, bc] = size (b); + + k = max ([max(a(:)), max(b(:))]); + m = 1; + while (k > (2^m-1)) + m = m + 1; + endwhile + + if (ar == br && ac == bc) + type = "matrix"; + flag = "overall"; + c = 1; + elseif (any ([ar, br] == 1)) + type = "row"; + flag = "row"; + if (ac != bc) + error ("biterr: A and B must have the same number of columns for row-wise comparison"); + endif + if (ar == 1) + a = ones (br, 1) * a; + else + b = ones (ar, 1) * b; + endif + elseif (any ([ac, bc] == 1)) + type = "column"; + flag = "column"; + if (ar != br) + error ("biterr: A and B must have the same number of rows for column-wise comparison"); + endif + if (ac == 1) + a = a * ones (1, bc); + else + b = b * ones (1, ac); + endif + else + error ("biterr: A and B must have the same size"); + endif + + k = 0; + for i = 1:length (varargin) + arg = varargin{i}; + if (ischar (arg)) + if (strcmp (arg, "row-wise")) + if (strcmp (type, "column")) + error ("biterr: row-wise comparison not possible with column inputs"); + endif + flag = "row"; + elseif (strcmp (arg, "column-wise")) + if (strcmp (type, "row")) + error ("biterr: column-wise comparison not possible with row inputs"); + endif + flag = "column"; + elseif (strcmp (arg, "overall")) + flag = "overall"; + else + error ("biterr: invalid option '%s'", arg); + endif + else + k = arg; + if (k < m) + error ("biterr: K must be >= the number of bits in the elements of A and B"); + endif + endif + endfor + + if (k == 0) + k = m; + endif + + ## Call the core error function to count the bit errors + ind = __errcore__ (a, b); + + switch (flag) + case "row" + if (strcmp (type, "matrix") && ac == 1) + num = ind; + else + num = sum (ind')'; + endif + rate = num / k / max (ac, bc); + case "column" + if (strcmp (type, "matrix") && ar == 1) + num = ind; + else + num = sum (ind); + endif + rate = num / k / max (ar, br); + case "overall" + num = sum (sum (ind)); + rate = num / k / max (ar, br) / max (ac, bc); + otherwise + error ("biterr: invalid comparison type '%s'", flag); + endswitch + +endfunction + +%% Test input validation +%!error biterr () +%!error biterr (1) +%!error biterr (1, 2, 3, 4, 5) +%!error biterr (10, 10, 2) diff --git a/inst/bsc.m b/inst/bsc.m new file mode 100644 index 0000000..2ec7900 --- /dev/null +++ b/inst/bsc.m @@ -0,0 +1,49 @@ +## Copyright (C) 2007 Sylvain Pelissier +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{y} =} bsc (@var{data}, @var{p}) +## Send @var{data} into a binary symmetric channel with probability +## @var{p} of error one each symbol. +## @end deftypefn + +function ndata = bsc (data, p) + + if (nargin != 2) + print_usage (); + endif + + if (! (isscalar (p) && p >= 0 && p <= 1)) + error ("bsc: P must be a positive scalar in the range [0,1]"); + endif + if (! (all (data(:) == fix (data(:))) && all (data(:) >= 0) + && all (data(:) <= 1))) + error ("bsc: DATA must be a binary sequence"); + endif + + ndata = data; + ndata(find (data == 0)) = randsrc (size (ndata(find (data == 0)), 1), size (ndata(find (data == 0)), 2), [-1 -2; 1-p p]); + ndata(find (data == 1)) = randsrc (size (ndata(find (data == 1)), 1), size (ndata(find (data == 1)), 2), [1 0; 1-p p]); + ndata(find (ndata == -1)) = 0; + ndata(find (ndata == -2)) = 1; + +endfunction + +%% Test input validation +%!error bsc () +%!error bsc (1) +%!error bsc (1, 2, 3) +%!error bsc (1, 2) +%!error bsc (2, 1) diff --git a/inst/comms.m b/inst/comms.m new file mode 100644 index 0000000..d178179 --- /dev/null +++ b/inst/comms.m @@ -0,0 +1,665 @@ +## Copyright (C) 2003 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} comms ("help") +## @deftypefnx {Function File} {} comms ("info") +## @deftypefnx {Function File} {} comms ("info", @var{mod}) +## @deftypefnx {Function File} {} comms ("test") +## @deftypefnx {Function File} {} comms ("test", @var{mod}) +## +## Manual and test code for the Octave Communications toolbox. There are +## 5 possible ways to call this function. +## +## @table @code +## @item comms ("help") +## Display this help message. Called with no arguments, this function also +## displays this help message +## @item comms ("info") +## Open the Communications toolbox manual +## @item comms ("info", @var{mod}) +## Open the Communications toolbox manual at the section specified by +## @var{mod} +## @item comms ("test") +## Run all of the test code for the Communications toolbox. +## @item comms ("test", @var{mod}) +## Run only the test code for the Communications toolbox in the module +## @var{mod}. +## @end table +## +## Valid values for the variable @var{mod} are +## +## @table @asis +## @item "all" +## All of the toolbox +## @item "random" +## The random signal generation and analysis package +## @item "source" +## The source coding functions of the package +## @item "block" +## The block coding functions +## @item "convol" +## The convolution coding package +## @item "modulation" +## The modulation package +## @item "special" +## The special filter functions +## @item "galois" +## The Galois fields package +## @end table +## +## Please note that this function file should be used as an example of the +## use of this toolbox. +## @end deftypefn + +function retval = comms (typ, tests) + + if (nargin < 1) + help ("comms"); + elseif (nargin < 2) + tests = "all"; + endif + + if (strcmp (tests, "all")) + nodename = "Top"; + elseif (strcmp (tests, "random")) + nodename = "Random Signals"; + elseif (strcmp (tests, "source")) + nodename = "Source Coding"; + elseif (strcmp (tests, "block")) + nodename = "Block Coding"; + elseif (strcmp (tests, "convol")) + nodename = "Convolutional Coding"; + elseif (strcmp (tests, "modulation")) + nodename = "Modulations"; + elseif (strcmp (tests, "special")) + nodename = "Special Fields"; + elseif (strcmp (tests, "galois")) + nodename = "Galois Fields"; + else + error ("comms: unrecognized package"); + endif + + if (strcmp (typ, "help")) + help ("comms"); + elseif (strcmp (typ, "info")) + infopaths = ["."]; + if (!isempty (char (strsplit (path, ":")))) + infopaths = [infopaths; char(strsplit (path, ":"))]; + endif + if (!isempty (char (strsplit (DEFAULT_LOADPATH, ":")))) + infopaths = [infopaths; char(strsplit (DEFAULT_LOADPATH, ":"))]; + endif + for i = 1:size (infopaths, 1) + infopath = deblank (infopaths(i,:)); + len = length (infopath); + if (len) + if (len > 1 && strcmp (infopath([len-1, len]), "//")) + [status, showfile] = system (["find '", infopath(1:len-1), ... + "' -name ", infofile]); + else + [status, showfile] = system (["find '", infopath, "' -name ", ... + infofile, " -maxdepth 1"]); + endif + if (length (showfile)) + break; + endif + endif + endfor + if (!exist ("showfile") || !length (showfile)) + error ("comms: info file not found"); + endif + if (showfile(length (showfile)) == "\n") + showfile = showfile(1:length (showfile)-1); + endif + + if (exist ("INFO_PROGAM")) + [testret, testout] = system (["'", INFO_PROGRAM, "' --version"]); + if (testret) + error ("comms: info command not found"); + else + system (["'", INFO_PROGRAM, "' --file '", showfile, "' --node '", ... + nodename, "'"]); + endif + else + [testret, testout] = system ("info --version"); + if (testret) + error ("comms: info command not found"); + else + system (["info --file '", showfile, "' --node '", nodename, "'"]); + endif + endif + elseif (strcmp (typ, "test")) + pso = page_screen_output (); + unwind_protect + page_screen_output (0); + + if (strcmp (tests, "random") || strcmp (tests, "all")) + fprintf ("\n<< Random Signals Package >>\n"); + fprintf (" Signal Creation: "); + n = 10; + m = 32; + x = randint (n, n, m); + if (any (size (x) != [10, 10]) || (max (x(:)) >= m) || (min (x(:) < 0))) + error ("FAILED"); + endif + x = randsrc (n, n, [1, 1i, -1, -1i,]); + if (any (size (x) != [10, 10]) || ... + !all (all ((x == 1) | (x == 1i) | (x == -1) | (x == -1i)))) + error ("FAILED"); + endif + x = randerr (n, n); + if (any (size (x) != [10, 10]) || any (sum (x') != ones (1, n))) + error ("FAILED"); + endif + + nse_30dBm_1Ohm = wgn (10000, 1, 30, 1, "dBm"); + nse_0dBW_1Ohm = wgn (10000, 1, 0, 1, "dBW"); + nse_1W_1Ohm = wgn (10000, 1, 1, 1, "linear"); + ## Standard deviations should be about 1... If it is greater than + ## some value flag an error + dev = [std(nse_30dBm_1Ohm), std(nse_0dBW_1Ohm), std(nse_1W_1Ohm)]; + if (any (dev > 1.5)) + error ("FAILED"); + endif + + x = [0:0.1:2*pi]; + y = sin (x); + noisy = awgn (y, 10, "dB", "measured"); + if (any (size (y) != size (noisy))) + error ("FAILED"); + endif + ## This is a pretty arbitrary test, but should pick up gross errors + if (any (abs (y - noisy) > 1)) + error ("FAILED"); + endif + fprintf ("PASSED\n"); + + fprintf (" Signal Analysis: "); + ## Protect!! Since bitxor might not be installed + try + n = 10; + m = 8; + msg = randint (n, n, 2^m); + noisy = bitxor (msg, diag (3*ones (1, n))); + [berr, brate] = biterr (msg, noisy, m); + if ((berr != 2*n) || (brate != 2/(n*m))) + error ("FAILED"); + endif + [serr, srate] = symerr (msg, noisy); + if ((serr != n) || (srate != 1/n)) + error ("FAILED"); + endif + catch + end_try_catch + ## Can not easily test eyediagram, scatterplot!! + fprintf ("PASSED\n"); + endif + if (strcmp (tests, "source") || strcmp (tests, "all")) + fprintf ("\n<< Source Coding Package >>\n"); + fprintf (" PCM Functions: "); + fprintf ("Not tested\n"); + fprintf (" Quantization Functions: "); + x = [0:0.1:2*pi]; + y = sin (x); + [tab, cod] = lloyds (y, 16); + [i, q, d] = quantiz (y, tab, cod); + if (abs (d) > 0.1) + error ("FAILED"); + endif + + mu = 0.1; + V = 1; + x = sin ([0:0.1:2*pi]); + y = compand (x, mu, V, "mu/compressor"); + z = compand (x, mu, V, "mu/expander"); + ## Again this is a pretty arbitrary test + if (max (abs (x-z)) > 0.1) + error ("FAILED"); + endif + fprintf ("PASSED\n"); + endif + if (strcmp (tests, "block") || strcmp (tests, "all")) + fprintf ("\n<< Block Coding Package >>\n"); + fprintf (" Cyclic Coding: "); + nsym = 100; + m = 4; + n = 2^m-1; # [15,11] Hamming code + k = n - m; + p = cyclpoly (n, k); + if (bi2de (p) != primpoly (m, "nodisplay")) + error ("FAILED"); + endif + [par, gen] = cyclgen (n, p); + if (any (any (gen2par (par) != gen))) + error ("FAILED"); + endif + if (gfweight (gen) != 3) + error ("FAILED"); + endif + + msg = randint (nsym, k); + code = encode (msg, n, k, "cyclic"); + noisy = mod (code + randerr (nsym, n), 2); + dec = decode (noisy, n, k, "cyclic"); + if (any (any (dec != msg))) + error ("FAILED"); + endif + try # Protect! If bitshift isn't install!! + msg = randint (nsym, 1, n); + code = encode (msg, n, k, "cyclic/decimal"); + noisy = mod (code + bitshift (1, randint (nsym, 1, n)), n+1); + dec = decode (noisy, n, k, "cyclic/decimal"); + if (any (dec != msg)) + error ("FAILED"); + endif + catch + end_try_catch + fprintf ("PASSED\n"); + + fprintf (" Hamming Coding: "); + nsym = 100; + m = 4; + [par, gen, n, k] = hammgen (m); + if (any (any (gen2par (par) != gen))) + error ("FAILED"); + endif + if (gfweight (gen) != 3) + error ("FAILED"); + endif + msg = randint (nsym, k); + code = encode (msg, n, k, "hamming"); + noisy = mod (code + randerr (nsym, n), 2); + dec = decode (noisy, n, k, "hamming"); + if (any (any (dec != msg))) + error ("FAILED"); + endif + try # Protect! If bitshift isn't install!! + msg = randint (nsym, 1, n); + code = encode (msg, n, k, "hamming/decimal"); + noisy = mod (code + bitshift (1, randint (nsym, 1, n)), n+1); + dec = decode (noisy, n, k, "hamming/decimal"); + if (any (dec != msg)) + error ("FAILED"); + endif + catch + end_try_catch + fprintf ("PASSED\n"); + + fprintf (" BCH Coding: "); + ## Setup + m = 5; + nsym = 100; + p = bchpoly (2^m - 1); + ## Pick a BCH code from the list at random + l = ceil (size (p, 1) * rand (1, 1)); + n = p(l,1); + k = p(l,2); + t = p(l,3); + ## Symbols represented by rows of binary matrix + msg = randint (nsym, k); + code = encode (msg, n, k, "bch"); + noisy = mod (code + randerr (nsym, n), 2); + dec = decode (noisy, n, k, "bch"); + if (any (any (dec != msg))) + error ("FAILED"); + endif + try # Protect! If bitshift isn't install!! + msg = randint (nsym, 1, n); + code = encode (msg, n, k, "bch/decimal"); + noisy = mod (code + bitshift (1, randint (nsym, 1, n)), n+1); + dec = decode (noisy, n, k, "bch/decimal"); + if (any (dec != msg)) + error ("FAILED"); + endif + catch + end_try_catch + fprintf ("PASSED\n"); + + fprintf (" Reed-Solomon Coding: "); + ## Test for a CCSDS like coder, but without dual-basis translation + mrs = 8; + nrs = 2^mrs -1; + krs = nrs - 32; + prs = 391; + fcr = 112; + step = 11; + + ## CCSDS generator polynomial + ggrs = rsgenpoly (nrs, krs, prs, fcr, step); + + ## Code two blocks + msg = gf (floor (2^mrs*rand (2, krs)), mrs, prs); + cde = rsenc (msg, nrs, krs, ggrs); + + ## Introduce errors + noisy = cde + [255, 0, 255, 0, 255, zeros(1, 250); ... + 0, 255, 0, 255, zeros(1, 251)]; + + ## Decode (better to pass fcr and step rather than gg for speed) + dec = rsdec (noisy, nrs, krs, fcr, step); + + if (any (dec != msg)) + error ("FAILED"); + endif + fprintf ("PASSED\n"); + endif + if (strcmp (tests, "convol") || strcmp (tests, "all")) + fprintf ("\n<< Convolutional Coding Package >>\n"); + fprintf (" Utility functions: "); + ## create a trellis, use poly2trellis and test with istrellis + fprintf ("Not tested\n"); + fprintf (" Coding: "); + ## use convenc, puncturing?? + fprintf ("Not tested\n"); + fprintf (" Viterbi: "); + ## use vitdec + fprintf ("Not tested\n"); + endif + if (strcmp (tests, "modulation") || strcmp (tests, "all")) + fprintf ("\n<< Modulation Package >>\n"); + fprintf (" Analog Modulation: "); + Fs = 100; + t = [0:1/Fs:2]; + x = sin (2*pi*t); + xq = x + 1i * cos (2*pi*t); + ## Can not test FM as it doesn't work !!! + if ((max (abs (x - ademodce (amodce (x, Fs, "pm"), Fs, "pm"))) > 0.001) || ... + (max (abs (x - ademodce (amodce (x, Fs, "am"), Fs, "am"))) > 0.001) || ... + (max (abs (xq - ademodce (amodce (xq, Fs, "qam"), Fs, "qam/cmplx"))) > 0.001)) + error ("FAILED"); + endif + fprintf ("PASSED\n"); + fprintf (" Digital Mapping: "); + m = 32; + n = 100; + x = randint (n, n, 32); + if ((x != demodmap (modmap (x, 1, 1, "ask", m), 1, 1, "ask", m)) || ... + (x != demodmap (modmap (x, 1, 1, "fsk", m), 1, 1, "fsk", m)) || ... + (x != demodmap (modmap (x, 1, 1, "msk"), 1, 1, "msk")) || ... + (x != demodmap (modmap (x, 1, 1, "psk", m), 1, 1, "psk", m)) || ... + (x != demodmap (modmap (x, 1, 1, "qask", m), 1, 1, "qask", m)) || ... + (x != demodmap (modmap (x, 1, 1, "qask/cir", ... + [floor(m/2), m - floor(m/2)]), 1, 1, "qask/cir", ... + [floor(m/2), m - floor(m/2)]))) + error ("FAILED"); + endif + fprintf ("PASSED\n"); + fprintf (" Digital Modulation: "); + fprintf ("Not tested\n"); + endif + if (strcmp (tests, "special") || strcmp (tests, "all")) + fprintf ("\n<< Special Filters Package >>\n"); + fprintf (" Hankel/Hilbert: "); + ## use hank2sys, hilbiir + fprintf ("Not tested\n"); + fprintf (" Raised Cosine: "); + ## use rcosflt, rcosiir rcosine, rcosfir + fprintf ("Not tested\n"); + endif + if (strcmp (tests, "galois") || strcmp (tests, "all")) + fprintf ("\n<< Galois Fields Package >>\n"); + ## Testing of the Galois Fields package + m = 3; ## must be greater than 2 + + fprintf (" Find primitive polynomials: "); + prims = primpoly (m, "all", "nodisplay"); + for i = 2^m:2^(m+1) - 1 + if (find (prims == i)) + if (!isprimitive (i)) + error ("Error in primitive polynomials"); + endif + else + if (isprimitive (i)) + error ("Error in primitive polynomials"); + endif + endif + endfor + fprintf ("PASSED\n"); + fprintf (" Create Galois variables: "); + n = 2^m-1; + gempty = gf ([], m); + gzero = gf (0, m); + gone = gf (1, m); + gmax = gf (n, m); + grow = gf (0:n, m); + gcol = gf ([0:n]', m); + matlen = ceil (sqrt (2^m)); + gmat = gf (reshape (mod ([0:matlen*matlen-1], 2^m), matlen, matlen), m); + fprintf ("PASSED\n"); + fprintf (" Access Galois structures: "); + if (gcol.m != m || gcol.prim_poly != primpoly (m, "min", ... + "nodisplay")) + error ("FAILED"); + endif + fprintf ("PASSED\n"); + fprintf (" Miscellaneous functions: "); + if (size (gmat) != [matlen, matlen]) + error ("FAILED"); + endif + if (length (grow) != 2^m) + error ("FAILED"); + endif + if (!any (grow) || all (grow) || any (gzero) || !all (gone)) + error ("FAILED"); + endif + if (isempty (gone) || !isempty (gempty)) + error ("FAILED"); + endif + tmp = diag (grow); + if (size (tmp, 1) != 2^m || size (tmp, 2) != 2^m) + error ("FAILED"); + endif + for i = 1:2^m + for j = 1:2^m + if ((i == j) && (tmp(i,j) != grow(i))) + error ("FAILED"); + elseif ((i != j) && (tmp(i,j) != 0)) + error ("FAILED"); + endif + endfor + endfor + tmp = diag (gmat); + if (length (tmp) != matlen) + error ("FAILED"); + endif + for i = 1:matlen + if (gmat(i,i) != tmp(i)) + error ("FAILED"); + endif + endfor + tmp = reshape (gmat, prod (size (gmat)), 1); + if (length (tmp) != prod (size (gmat))) + error ("FAILED"); + endif + if (exp (log (gf ([1:n], m))) != [1:n]) + error ("FAILED"); + endif + tmp = sqrt (gmat); + if (tmp .* tmp != gmat) + error ("FAILED"); + endif + + fprintf ("PASSED\n"); + fprintf (" Unary operators: "); + tmp = - grow; + if (tmp != grow) + error ("FAILED"); + endif + tmp = !grow; + if (tmp(1) != 1) + error ("FAILED"); + endif + if (any (tmp(2:length (tmp)))) + error ("FAILED"); + endif + tmp = gmat'; + for i = 1:size (gmat, 1) + for j = 1:size (gmat, 2) + if (gmat(i,j) != tmp(j,i)) + error ("FAILED"); + endif + endfor + endfor + fprintf ("PASSED\n"); + fprintf (" Arithmetic operators: "); + if (any (gmat + gmat)) + error ("FAILED"); + endif + multbl = gcol * grow; + elsqr = gcol .* gcol; + elsqr2 = gcol .^ gf (2, m); + for i = 1:length (elsqr) + if (elsqr(i) != multbl(i,i)) + error ("FAILED"); + endif + endfor + for i = 1:length (elsqr) + if (elsqr(i) != elsqr2(i)) + error ("FAILED"); + endif + endfor + tmp = grow(2:length (grow)) ./ gcol(2:length (gcol))'; + if (length (tmp) != n || any (tmp != ones (1, length (grow) - 1))) + error ("FAILED"); + endif + fprintf ("PASSED\n"); + fprintf (" Logical operators: "); + if (grow(1) != gzero || grow(2) != gone || grow(2^m) != n) + error ("FAILED"); + endif + if (!(grow(1) == gzero) || any (grow != gcol')) + error ("FAILED"); + endif + fprintf ("PASSED\n"); + + fprintf (" Polynomial manipulation: "); + poly1 = gf ([2, 4, 5, 1], 3); + poly2 = gf ([1, 2], 3); + sumpoly = poly1 + [0, 0, poly2]; ## Already test "+" + mulpoly = conv (poly1, poly2); ## multiplication + poly3 = [poly, remd] = deconv (mulpoly, poly2); + if (!isequal (poly1, poly3)) + error ("FAILED"); + endif + if (any (remd)) + error ("FAILED"); + endif + x0 = gf ([0, 1, 2, 3], 3); + y0 = polyval (poly1, x0); + alph = gf (2, 3); + y1 = alph * x0.^3 + alph.^2 * x0.^2 + (alph.^2+1) *x0 + 1; + if (!isequal (y0, y1)) + error ("FAILED"); + endif + roots1 = roots (poly1); + ck1 = polyval (poly1, roots1); + if (any (ck1)) + error ("FAILED"); + endif + b = minpol (alph); + bpoly = bi2de (b.x, "left-msb"); + if (bpoly != alph.prim_poly) + error ("FAILED"); + endif + c = cosets (3); + c2 = c{2}; + mpol = minpol (c2(1)); + for i = 2:length (c2) + if (mpol != minpol (c2(i))) + error ("FAILED"); + endif + endfor + fprintf ("PASSED\n"); + + fprintf (" Linear Algebra: "); + [l, u, p] = lu (gmat); + if (any (l*u - p*gmat)) + error ("FAILED"); + endif + g1 = inv (gmat); + g2 = gmat ^ -1; + if (any (g1*gmat != eye (matlen))) + error ("FAILED"); + endif + if (any (g1 != g2)) + error ("FAILED"); + endif + matdet = 0; + while (!matdet) + granmat = gf (floor (2^m*rand (matlen)), m); + matdet = det (granmat); + endwhile + matrank = rank (granmat); + smallcol = gf ([0:matlen-1], m)'; + sol1 = granmat \ smallcol; + sol2 = smallcol' / granmat; + if (any (granmat * sol1 != smallcol)) + error ("FAILED"); + endif + if (any (sol2 * granmat != smallcol')) + error ("FAILED"); + endif + fprintf ("PASSED\n"); + fprintf (" Signal Processing functions: "); + b = gf ([1, 0, 0, 1, 0, 1, 0, 1], m); + a = gf ([1, 0, 1, 1], m); + x = gf ([1, zeros(1, 99)], m); + y0 = filter (b, a, x); + y1 = conv (grow+1, grow); + y2 = grow * convmtx (grow+1, length (grow)); + if (any (y1 != y2)) + error ("FAILED"); + endif + [y3, remd] = deconv (y2, grow+1); + if (any (y3 != grow)) + error ("FAILED"); + endif + if (any (remd)) + error ("FAILED"); + endif + alph = gf (2, m); + x = gf (floor (2^m*rand (n, 1)), m); + fm = dftmtx (alph); + ifm = dftmtx (1/alph); + y0 = fft (x); + y1 = fm * x; + if (any (y0 != y1)) + error ("FAILED"); + endif + z0 = ifft (y0); + z1 = ifm * y1; + if (any (z0 != x)) + error ("FAILED"); + endif + if (any (z1 != x)) + error ("FAILED"); + endif + fprintf ("PASSED\n"); + + endif + fprintf ("\n"); + unwind_protect_cleanup + page_screen_output (pso); + end_unwind_protect + else + print_usage (); + endif + +endfunction + +%!test +%! try comms ("test"); +%! catch disp (lasterr ()); end_try_catch diff --git a/inst/compand.m b/inst/compand.m new file mode 100644 index 0000000..fdbef60 --- /dev/null +++ b/inst/compand.m @@ -0,0 +1,121 @@ +## Copyright (C) 2001 Paul Kienzle +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{y} =} compand (@var{x}, @var{mu}, @var{V}, "mu/compressor") +## @deftypefnx {Function File} {@var{y} =} compand (@var{x}, @var{mu}, @var{V}, "mu/expander") +## @deftypefnx {Function File} {@var{y} =} compand (@var{x}, @var{mu}, @var{V}, "A/compressor") +## @deftypefnx {Function File} {@var{y} =} compand (@var{x}, @var{mu}, @var{V}, "A/expander") +## +## Compresses and expanding the dynamic range of a signal using a mu-law or +## or A-law algorithm. +## +## The mu-law compressor/expander for reducing the dynamic range, is used +## if the fourth argument of @code{compand} starts with "mu/". Whereas the +## A-law compressor/expander is used if @code{compand} starts with "A/". +## The mu-law algorithm uses the formulation +## +## @tex +## $$ +## y = {V log (1 + \\mu / V \\|x\\|) \\over log (1 + \\mu)} sgn(x) +## $$ +## @end tex +## @ifnottex +## @example +## @group +## +## V log (1 + \mu/V |x|) +## y = -------------------- sgn(x) +## log (1 + \mu) +## +## @end group +## @end example +## @end ifnottex +## +## while the A-law algorithm used the formulation +## +## @tex +## $$ +## y = { \\left\{ \\matrix{ {A / (1 + log A) x}, & 0 <= \\|x\\| <= V/A \\cr +## & \\cr +## {V log (1 + log(A/V \\|x\\|) ) \\over 1 + logA}, & +## V/A < \\|x\\| <= V} \\right. } +## $$ +## @end tex +## @ifnottex +## @example +## @group +## +## / A / (1 + log A) x, 0 <= |x| <= V/A +## | +## y = < V ( 1 + log (A/V |x|) ) +## | ----------------------- sgn(x), V/A < |x| <= V +## \ 1 + log A +## @end group +## @end example +## @end ifnottex +## +## Neither converts from or to audio file ulaw format. Use mu2lin or lin2mu +## instead. +## +## @seealso{m2ulin, lin2mu} +## @end deftypefn + +function y = compand (x, mu, V, stype) + + if (nargin != 3 && nargin != 4) + print_usage (); + endif + if (nargin < 4) + stype = "mu/compressor"; + else + stype = tolower (stype); + endif + + if (strcmp (stype, "mu/compressor")) + y = (V/log (1 + mu)) * log (1 + (mu/V)*abs (x)) .* sign (x); + elseif (strcmp (stype, "mu/expander")) + y = (V/mu) * (exp (abs (x) * (log (1 + mu)/V)) - 1) .* sign (x); + elseif (strcmp (stype, "a/compressor")) + y = zeros (size (x)); + idx = find (abs (x) <= V/mu); + if (idx) + y(idx) = (mu / (1 + log (mu))) * abs (x(idx)); + endif + idx = find (abs (x) > V/mu); + if (idx) + y(idx) = (V / (1 + log (mu))) * (1 + log ((mu/V) * abs (x(idx)))); + endif + y = y .* sign (x); + elseif (strcmp (stype, "a/expander")) + y = zeros (size (x)); + idx = find (abs (x) <= V / (1 + log (mu))); + if (idx) + y(idx) = ((1 + log (mu))/mu) * abs (x(idx)); + endif + idx = find (abs (x) > V / (1 + log (mu))); + if (idx) + y(idx) = exp (((1 + log (mu))/V) * abs (x(idx)) - 1) * (V/mu); + endif + y = y .* sign (x); + endif + +endfunction + +%% Test input validation +%!error compand () +%!error compand (1) +%!error compand (1, 2) +%!error compand (1, 2, 3, 4, 5) diff --git a/inst/convenc.m b/inst/convenc.m new file mode 100644 index 0000000..588dbdc --- /dev/null +++ b/inst/convenc.m @@ -0,0 +1,119 @@ +## Copyright (C) 2013 Mike Miller +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{y} =} convenc (@var{msg}, @var{t}) +## @deftypefnx {Function File} {@var{y} =} convenc (@var{msg}, @var{t}, @var{punct}) +## @deftypefnx {Function File} {@var{y} =} convenc (@var{msg}, @var{t}, @var{punct}, @var{s0}) +## @deftypefnx {Function File} {[@var{y}, @var{state_end}] =} convenc (@dots{}) +## Encode the binary vector @var{msg} with the convolutional encoder +## described by the trellis structure @var{t}. +## +## The rate @math{k/n} convolutional encoder encodes @math{k} bits at a +## time from the input vector and produces @math{n} bits at a time into the +## output vector. The input @var{msg} must have a length that is a multiple +## of @math{k}. +## +## If the initial state @var{s0} is specified, it indicates the internal +## state of the encoder when the first @math{k} input bits are fed in. The +## default value of @var{s0} is 0. +## +## The optional output argument @var{state_end} indicates the internal state +## of the encoder after the last bits are encoded. This allows the state of +## the encoder to be saved and applied to the next call to @code{convenc} to +## process data in blocks. +## +## @seealso{poly2trellis} +## @end deftypefn + +function [y, state_end] = convenc (msg, t, punct, s0 = 0) + + if (nargin < 2 || nargin > 4) + print_usage (); + endif + + if (! (isvector (msg) && all (msg == 0 | msg == 1))) + error ("convenc: MSG must be a binary vector"); + endif + + if (! istrellis (t)) + error ("convenc: T must be a valid trellis structure"); + endif + + if (nargin < 3) + punct = []; + endif + if (! isempty (punct)) + warning ("convenc: ignoring PUNCT, puncturing is not yet implemented"); + endif + + ## FIXME: Add error check for valid punct binary vector + + if (nargin == 4 && ! (isscalar (s0) && s0 == fix (s0) && s0 >= 0 + && s0 < t.numStates)) + error ("convenc: S must be an integer in the range [0,T.numStates-1]"); + endif + + k = log2 (t.numInputSymbols); + n = log2 (t.numOutputSymbols); + + in_symbols = numel (msg) / k; + if (in_symbols != fix (in_symbols)) + error ("convenc: length of MSG must be a multiple of k"); + endif + + transpose = (columns (msg) == 1); + msg = msg(:).'; + + state = s0; + y = []; + + ## FIXME: Implement output puncturing + + for idx = 1:k:numel (msg) + in_sym = bi2de (msg(idx:idx+k-1), "left-msb"); + out_sym = oct2dec (t.outputs(state+1,in_sym+1)); + state = t.nextStates(state+1,in_sym+1); + out_bits = de2bi (out_sym, n, "left-msb"); + y = [y out_bits]; + endfor + + if (transpose) + y = y(:); + endif + + if (nargout > 1) + state_end = state; + endif + +endfunction + +%!test +%! t = poly2trellis (1, 1); +%! m = randi ([0 1], 128, 1); +%! [y, s] = convenc (m, t); +%! assert (y, m) +%! assert (s, 0) +%!test +%! t = poly2trellis (3, [7 5]); +%! m = [1 1 0 1 1 1 0 0 1 0 0 0]; +%! y = [1 1 0 1 0 1 0 0 0 1 1 0 0 1 1 1 1 1 1 0 1 1 0 0]; +%! assert (convenc (m, t), y) + +%% Test input validation +%!error convenc () +%!error convenc (1) +%!error convenc (1, 2) +%!error convenc (1, 2, 3, 4, 5) diff --git a/inst/cosets.m b/inst/cosets.m new file mode 100644 index 0000000..60a4da2 --- /dev/null +++ b/inst/cosets.m @@ -0,0 +1,57 @@ +## Copyright (C) 2002 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} cosets (@var{m}, @var{prim}) +## +## Finds the elements of GF(2^@var{m}) with primitive polynomial @var{prim}, +## that share the same minimum polynomial. Returns a cell array of the +## partitioning of GF(2^@var{m}). +## @end deftypefn + +function c = cosets (m, prim) + + if (nargin == 1) + prim = 0; ## This flags to use default primitive + elseif (nargin != 2) + print_usage (); + endif + + n = 2^m-1; + found = zeros (1, n); + c{1} = gf (1, m, prim); + found(1) = 1; + nc = 2; + f = log (gf (1:n, m, prim)); + + while (!all (found)) + t = find (!found); + idx = f(t(find (f(t) == min (f(t).x)))).x; + set = idx; + r = rem (idx*2, n); + while (r > idx) + set = [set, r]; + r = rem (r*2, n); + endwhile + c{nc} = gf (sort (exp (gf (set, m, prim)).x), m, prim); + found(c{nc}.x) = ones (1, length (c{nc})); + nc = nc + 1; + endwhile + +endfunction + +%% Test input validation +%!error cosets () +%!error cosets (1, 2, 3) diff --git a/inst/de2bi.m b/inst/de2bi.m new file mode 100644 index 0000000..568834b --- /dev/null +++ b/inst/de2bi.m @@ -0,0 +1,157 @@ +## Copyright (C) 2020 Nicholas Jankowski +## Copyright (C) 2015 Michael Hirsch +## Copyright (C) 2001 Laurent Mazet +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{b} =} de2bi (@var{d}) +## @deftypefnx {Function File} {@var{b} =} de2bi (@var{d}, @var{n}) +## @deftypefnx {Function File} {@var{b} =} de2bi (@var{d}, @var{n}, @var{p}) +## @deftypefnx {Function File} {@var{b} =} de2bi (@var{d}, @dots{}, @var{f}) +## +## Convert a non-negative integer to bit vector. +## +## The variable @var{d} must be a vector of non-negative integers. @code{de2bi} +## then returns a matrix where each row represents the binary representation +## of elements of @var{d}. If @var{n} is defined then the returned matrix +## will have @var{n} columns. This number of columns can be either larger +## than the minimum needed and zeros will be added to the msb of the +## binary representation or smaller than the minimum in which case the +## least-significant part of the element is returned. +## +## If @var{p} is defined then it is used as the base for the decomposition +## of the returned values. That is the elements of the returned value are +## between '0' and 'p-1'. (@var{p} must have a value of 2 or higher.) +## +## The variable @var{f} defines whether the first or last element of @var{b} +## is considered to be the most-significant. Valid values of @var{f} are +## "right-msb" or "left-msb". By default @var{f} is "right-msb". +## +## @seealso{bi2de} +## @end deftypefn + +function b = de2bi (d, varargin) + + if (nargin == 1) + p = 2; + n = floor ( log (max (max (d), 1)) ./ log (p) ) + 1; + f = "right-msb"; + else + n = []; + p = []; + f = []; + + % first pull out non-numeric inputs + msb_flag_chk = cellfun (@ischar, varargin); + if any(msb_flag_chk) + if sum (msb_flag_chk) > 1 + %should never be more than one string input + print_usage (); + else + f = varargin{msb_flag_chk}; + varargin = varargin(~msb_flag_chk); + endif + else + f = "right-msb"; + endif + + %varargin should now be length 0, 1, or 2, all non-char + numer_inputs = numel (varargin); + + if numer_inputs == 2 + n = varargin{1}; + p = varargin{2}; + elseif numer_inputs == 1 + n = varargin{1}; + p = 2; + elseif numer_inputs == 0 + p = 2; + n = floor ( log (max (max (d), 1)) ./ log (p) ) + 1; + else + print_usage (); + endif + + %if user passed any [] as inputs, set to defaults + if isempty (p) + p = 2; + endif + if isempty (n) + n = floor ( log (max (max (d), 1)) ./ log (p) ) + 1; + endif + if isempty (f) + f = "right-msb"; + endif + endif + + ##TODO: previous versions permitted negative base, but did not actually output + ## values according to negative-base system rules. If this is desired the p<0 + ## check can be removed and proper negative-base arithmetic can be added. + ## Also removed p=0 and 1 which caused errors in n-calculation. + if (p < 2) + error ("de2bi: conversion base must be 2 or greater"); + endif + + classorig = class(d); + d = double(d(:)); + p = double(p); + if (! (all (d == fix (d)) && all (d >= 0))) + error ("de2bi: all elements of D must be non-negative integers"); + endif + + if (isempty (n)) + n = floor ( log (max (max (d), 1)) ./ log (p) ) + 1; + endif + + power = ones (length (d), 1) * (p .^ [0 : n-1] ); + d = d * ones (1, n); + b = floor (rem (d, p*power) ./ power); + + if (strcmp (f, "left-msb")) + b = b(:,columns (b):-1:1); + elseif (!strcmp (f, "right-msb")) + error ("de2bi: invalid option '%s'", f); + endif + + b=cast(b,classorig); + +endfunction + +%!shared x +%! x = randi ([0 2^16-1], 100, 1); +%!assert (de2bi (0), 0) +%!assert (de2bi (1), 1) +%!assert (de2bi (uint8(31), ones (1,5))) +%!assert (class(de2bi(uint8(31))), 'uint8') +%!assert (de2bi (255), ones (1, 8)) +%!assert (de2bi (255, [], 256), 255) +%!assert (de2bi (1023, 8, 8), [7 7 7 1 0 0 0 0]) +%!assert (size (de2bi (x, 16)), [100 16]) +%!assert (de2bi (x, 16, "right-msb"), de2bi (x, 16)) +%!assert (de2bi (x, 16, "left-msb"), fliplr (de2bi (x, 16))) +%!assert (de2bi (13, "right-msb"), [1 0 1 1]) +%!assert (de2bi (13, "left-msb"), [1 1 0 1]) +%!assert (de2bi (13, [], "right-msb"), [1 0 1 1]) +%!assert (de2bi (13, [], [], "right-msb"), [1 0 1 1]) + +%% Test input validation +%!error de2bi () +%!error de2bi (1, 2, 3, 4, 5) +%!error de2bi (1, 2, 3, 4) +%!error de2bi (1, 2, 3, "invalid") +%!error de2bi (0.1) +%!error de2bi (-1) +%!error de2bi (5,[],1) +%!error de2bi (5,[],0) +%!error de2bi (5,[],-2) diff --git a/inst/decode.m b/inst/decode.m new file mode 100644 index 0000000..17c5d65 --- /dev/null +++ b/inst/decode.m @@ -0,0 +1,295 @@ +## Copyright (C) 2003 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{msg} =} decode (@var{code}, @var{n}, @var{k}) +## @deftypefnx {Function File} {@var{msg} =} decode (@var{code}, @var{n}, @var{k}, @var{typ}) +## @deftypefnx {Function File} {@var{msg} =} decode (@var{code}, @var{n}, @var{k}, @var{typ}, @var{opt1}) +## @deftypefnx {Function File} {@var{msg} =} decode (@var{code}, @var{n}, @var{k}, @var{typ}, @var{opt1}, @var{opt2}) +## @deftypefnx {Function File} {[@var{msg}, @var{err}] =} decode (@dots{}) +## @deftypefnx {Function File} {[@var{msg}, @var{err}, @var{ccode}] =} decode (@dots{}) +## @deftypefnx {Function File} {[@var{msg}, @var{err}, @var{ccode}, @var{cerr}] =} decode (@dots{}) +## +## Top level block decoder. This function makes use of the lower level +## functions such as @code{cyclpoly}, @code{cyclgen}, @code{hammgen}, and +## @code{bchenco}. The coded message to decode is pass in @var{code}, the +## codeword length is @var{n} and the message length is @var{k}. This +## function is used to decode messages using either: +## +## @table @asis +## @item A [n,k] linear block code defined by a generator matrix +## @item A [n,k] cyclic code defined by a generator polynomial +## @item A [n,k] Hamming code defined by a primitive polynomial +## @item A [n,k] BCH code code defined by a generator polynomial +## @end table +## +## The type of coding to use is defined by the variable @var{typ}. This +## variable is a string taking one of the values +## +## @table @code +## @item "linear" +## @itemx "linear/binary" +## A linear block code is assumed with the message @var{msg} being in a +## binary format. In this case the argument @var{opt1} is the generator +## matrix, and is required. Additionally, @var{opt2} containing the +## syndrome lookup table (see @code{syndtable}) can also be passed. +## @item "cyclic" +## @itemx "cyclic/binary" +## A cyclic code is assumed with the message @var{msg} being in a binary +## format. The generator polynomial to use can be defined in @var{opt1}. +## The default generator polynomial to use will be +## @code{cyclpoly (@var{n}, @var{k})}. Additionally, @var{opt2} containing the +## syndrome lookup table (see @code{syndtable}) can also be passed. +## @item "hamming" +## @itemx "hamming/binary" +## A Hamming code is assumed with the message @var{msg} being in a binary +## format. In this case @var{n} must be of an integer of the form +## @code{2^@var{m}-1}, where @var{m} is an integer. In addition @var{k} +## must be @code{@var{n}-@var{m}}. The primitive polynomial to use can +## be defined in @var{opt1}. The default primitive polynomial to use is +## the same as defined by @code{hammgen}. The variable @var{opt2} should +## not be defined. +## @item "bch" +## @itemx "bch/binary" +## A BCH code is assumed with the message @var{msg} being in a binary +## format. The primitive polynomial to use can be defined in @var{opt2}. +## The error correction capability of the code can also be defined in +## @var{opt1}. Use the empty matrix [] to let the error correction +## capability take the default value. +## @end table +## +## In addition the argument "binary" above can be replaced with "decimal", +## in which case the message is assumed to be a decimal vector, with each +## value representing a symbol to be coded. The binary format can be in two +## forms +## +## @table @code +## @item An @var{x}-by-@var{n} matrix +## Each row of this matrix represents a symbol to be decoded +## @item A vector with length divisible by @var{n} +## The coded symbols are created from groups of @var{n} elements of this vector +## @end table +## +## The decoded message is return in @var{msg}. The number of errors encountered +## is returned in @var{err}. If the coded message format is "decimal" or a +## "binary" matrix, then @var{err} is a column vector having a length equal +## to the number of decoded symbols. If @var{code} is a "binary" vector, then +## @var{err} is the same length as @var{msg} and indicated the number of +## errors in each symbol. If the value @var{err} is positive it indicates the +## number of errors corrected in the corresponding symbol. A negative value +## indicates an uncorrectable error. The corrected code is returned in +## @var{ccode} in a similar format to the coded message @var{msg}. The +## variable @var{cerr} contains similar data to @var{err} for @var{ccode}. +## +## It should be noted that all internal calculations are performed in the +## binary format. Therefore for large values of @var{n}, it is preferable +## to use the binary format to pass the messages to avoid possible rounding +## errors. Additionally, if repeated calls to @code{decode} will be performed, +## it is often faster to create a generator matrix externally with the +## functions @code{hammgen} or @code{cyclgen}, rather than let @code{decode} +## recalculate this matrix at each iteration. In this case @var{typ} should +## be "linear". The exception to this case is BCH codes, where the required +## syndrome table is too large. The BCH decoder, decodes directly from the +## polynomial never explicitly forming the syndrome table. +## +## @seealso{encode, cyclgen, cyclpoly, hammgen, bchdeco, bchpoly, syndtable} +## @end deftypefn + +function [msg, err, ccode, cerr] = decode (code, n, k, typ, opt1, opt2) + + if (nargin < 3 || nargin > 6) + print_usage (); + endif + + if (! (isscalar (n) && n == fix (n) && n >= 3)) + error ("decode: N must be an integer greater than 3"); + endif + + if (! (isscalar (k) && k == fix (k) && k <= n)) + error ("decode: K must be an integer less than N"); + endif + + if (nargin > 3) + if (!ischar (typ)) + error ("decode: TYP must be a string"); + else + ## Why the hell did matlab decide on such an ugly way of passing 2 args! + if (strcmp (typ, "linear") || strcmp (typ, "linear/binary")) + coding = "linear"; + msgtyp = "binary"; + elseif (strcmp (typ, "linear/decimal")) + coding = "linear"; + msgtyp = "decimal"; + elseif (strcmp (typ, "cyclic") || strcmp (typ, "cyclic/binary")) + coding = "cyclic"; + msgtyp = "binary"; + elseif (strcmp (typ, "cyclic/decimal")) + coding = "cyclic"; + msgtyp = "decimal"; + elseif (strcmp (typ, "bch") || strcmp (typ, "bch/binary")) + coding = "bch"; + msgtyp = "binary"; + elseif (strcmp (typ, "bch/decimal")) + coding = "bch"; + msgtyp = "decimal"; + elseif (strcmp (typ, "hamming") || strcmp (typ, "hamming/binary")) + coding = "hamming"; + msgtyp = "binary"; + elseif (strcmp (typ, "hamming/decimal")) + coding = "hamming"; + msgtyp = "decimal"; + else + error ("decode: invalid coding and/or message TYP '%s'", typ); + endif + endif + else + coding = "hamming"; + msgtyp = "binary"; + endif + + if (strcmp (msgtyp, "binary")) + vecttyp = 0; + if ((max (code(:)) > 1) || (min (code(:)) < 0)) + error ("decode: CODE must be a binary matrix"); + endif + [ncodewords, n2] = size (code); + len = n2*ncodewords; + if (len/n != fix (len/n)) + error ("decode: size of CODE must be a multiple of N"); + endif + if (min (n2, ncodewords) == 1) + vecttyp = 1; + ncodewords = len / n; + code = reshape (code, n, ncodewords); + code = code'; + elseif (n2 != n) + error ("decode: CODE must be a matrix with N columns"); + endif + else + if (!isvector (code)) + error ("decode: decimal CODE type must be a vector"); + endif + if (max (code) > 2^n-1 || min (code) < 0) + error ("decode: all elements of CODE must be in the range [0,2^N-1]"); + endif + ncodewords = length (code); + code = de2bi (code(:), n); + endif + + if (strcmp (coding, "bch")) + if (nargin < 5 || isempty (opt1)) + tmp = bchpoly (n, k, "probe"); + t = tmp(3); + else + t = opt1; + endif + + if (nargin > 5) + [msg err ccode] = bchdeco (code, k, t, opt2); + else + [msg err ccode] = bchdeco (code, k, t); + endif + cerr = err; + else + if (strcmp (coding, "linear")) + if (nargin > 4) + gen = opt1; + if ((size (gen, 1) != k) || (size (gen, 2) != n)) + error ("decode: generator matrix must be of size KxN"); + endif + par = gen2par (gen); + if (nargin > 5) + st = opt2; + else + st = syndtable (par); + endif + else + error ("decode: linear coding requires a generator matrix"); + endif + elseif (strcmp (coding, "cyclic")) + if (nargin > 4) + [par, gen] = cyclgen (n, opt1); + else + [par, gen] = cyclgen (n, cyclpoly (n, k)); + endif + if (nargin > 5) + ## FIXME: Should we check that the generator polynomial is + ## consistent with the syndrome table. Where is the acceleration in + ## this case??? + st = opt2; + else + st = syndtable (par); + endif + else + m = log2 (n + 1); + if (! (m == fix (m) && m >= 3 && m <= 16)) + error ("decode: N must be equal to 2^M-1 for integer M in the range [3,16]"); + endif + if (k != (n-m)) + error ("decode: K must be equal to N-M for Hamming decoder"); + endif + if (nargin > 4) + [par, gen] = hammgen (m, opt1); + else + [par, gen] = hammgen (m); + endif + if (nargin > 5) + error ("decode: too many arguments for Hamming decoder"); + else + st = syndtable (par); + endif + endif + + errvec = st(bi2de ((mod (par * code', 2))', "left-msb") + 1,:); + ccode = mod (code+errvec, 2); + err = sum (errvec'); + cerr = err; + if (isequal (gen(:,1:k), eye (k))) + msg = ccode(:,1:k); + elseif (isequal (gen(:,n-k+1:n), eye (k))) + msg = ccode(:,n-k+1:n); + else + error ("decode: generator matrix must be in standard form"); + endif + endif + + if (strcmp (msgtyp, "binary") && vecttyp == 1) + msg = msg'; + msg = msg(:); + ccode = ccode'; + ccode = ccode(:); + err = ones (k, 1) * err; + err = err(:); + cerr = ones (n, 1) * cerr; + cerr = cerr(:); + else + err = err(:); + cerr = cerr(:); + if (strcmp (msgtyp, "decimal")) + msg = bi2de (msg); + ccode = bi2de (ccode); + endif + endif + +endfunction + +%% Test input validation +%!error decode () +%!error decode (1) +%!error decode (1, 2) +%!error decode (1, 2, 3, 4, 5, 6, 7) +%!error decode (1, 2, 3) +%!error decode (1, 5, 6) +%!error decode (1, 5, 3, "invalid") diff --git a/inst/deintrlv.m b/inst/deintrlv.m new file mode 100644 index 0000000..b459500 --- /dev/null +++ b/inst/deintrlv.m @@ -0,0 +1,53 @@ +## Copyright (C) 2008 Sylvain Pelissier +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{deintrlvd} =} deintrlv (@var{data}, @var{elements}) +## Restore elements of @var{data} according to @var{elements}. +## @seealso{intrlv} +## @end deftypefn + +function deintrlvd = deintrlv (data, elements) + + if (nargin != 2) + print_usage (); + endif + + if (!isvector (elements)) + error ("deintrlv: ELEMENTS must be a vector"); + endif + + ind = 1:length (elements); + invperm(elements) = ind; + + if (isvector (data)) + if (length (elements) != length (data) || any (sort (elements) != 1:length (data))) + error ("deintrlv: ELEMENTS must be a permutation of DATA indices"); + endif + deintrlvd = data(invperm); + else + if (length (elements) != size (data, 1) || any (sort (elements) != 1:size (data, 1))) + error ("deintrlv: ELEMENTS must be a permutation of DATA indices"); + endif + deintrlvd = data(invperm,:); + endif + +endfunction + +%% Test input validation +%!error deintrlv () +%!error deintrlv (1) +%!error deintrlv (1, 2, 3) +%!error deintrlv ([0 0], [2 3]) diff --git a/inst/demodmap.m b/inst/demodmap.m new file mode 100644 index 0000000..abdff91 --- /dev/null +++ b/inst/demodmap.m @@ -0,0 +1,243 @@ +## Copyright (C) 2003 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {z =} demodmap (@var{y}, @var{fd}, @var{fs}, "ask", @var{m}) +## @deftypefnx {Function File} {z =} demodmap (@var{y}, @var{fd}, @var{fs}, "fsk", @var{m}, @var{tone}) +## @deftypefnx {Function File} {z =} demodmap (@var{y}, @var{fd}, @var{fs}, "msk") +## @deftypefnx {Function File} {z =} demodmap (@var{y}, @var{fd}, @var{fs}, "psk", @var{m}) +## @deftypefnx {Function File} {z =} demodmap (@var{y}, @var{fd}, @var{fs}, "qask", @var{m}) +## @deftypefnx {Function File} {z =} demodmap (@var{y}, @var{fd}, @var{fs}, "qask/cir", @var{nsig}, @var{amp}, @var{phs}) +## @deftypefnx {Function File} {z =} demodmap (@var{y}, @var{fd}, @var{fs}, "qask/arb", @var{inphase}, @var{quadr}) +## @deftypefnx {Function File} {z =} demodmap (@var{y}, @var{fd}, @var{fs}, "qask/arb", @var{map}) +## @deftypefnx {Function File} {z =} demodmap (@var{y}, [@var{fd}, @var{off}], @dots{}) +## +## Demapping of an analog signal to a digital signal. The function +## @code{demodmap} must have at least three input arguments and one output +## argument. Argument @var{y} is a complex variable representing the analog +## signal to be demapped. The variables @var{fd} and @var{fs} are the +## sampling rate of the of digital signal and the sampling rate of the +## analog signal respectively. It is required that @code{@var{fs}/@var{fd}} +## is an integer. +## +## The available mapping of the digital signal are +## +## @table @asis +## @item "ask" +## Amplitude shift keying +## @item "fsk" +## Frequency shift keying +## @item "msk" +## Minimum shift keying +## @item "psk" +## Phase shift keying +## @item "qask" +## @itemx "qsk" +## @itemx "qam" +## Quadrature amplitude shift keying +## @end table +## +## In addition the "qask", "qsk" and "qam" method can be modified with the +## flags "/cir" or "/arb". That is "qask/cir" and "qask/arb", etc are valid +## methods and give circular- and arbitrary-qask mappings respectively. Also +## the method "fsk" and "msk" can be modified with the flag "/max", in which +## case @var{y} is assumed to be a matrix with @var{m} columns, representing +## the symbol correlations. +## +## The variable @var{m} is the order of the modulation to use. By default +## this is 2, and in general should be specified. +## +## For "qask/cir", the additional arguments are the same as for +## @code{apkconst}, and you are referred to @code{apkconst} for the definitions +## of the additional variables. +## +## For "qask/arb", the additional arguments @var{inphase} and @var{quadr} give +## the in-phase and quadrature components of the mapping, in a similar mapping +## to the outputs of @code{qaskenco} with one argument. Similar @var{map} +## represents the in-phase and quadrature components of the mapping as +## the real and imaginary parts of the variable @var{map}. +## @seealso{modmap, ddemodce, ademodce, apkconst, qaskenco} +## @end deftypefn + +function z = demodmap (y, fd, fs, varargin) + + if (nargin < 3) + print_usage (); + endif + + if (!isscalar (fs) || !isreal (fs) || !isreal (fd) || fs <= 0 || fd <= 0) + error ("demodmap: FD and FS must be positive real values"); + endif + if (abs (fs/fd - fix (fs/fd)) > eps) + error ("demodmap: FS must be an integer multiple of FD"); + endif + + if (!isscalar (fd)) + if (isequal (size (fd), [1, 2])) + off = fd(2); + fd = fd(1); + else + error ("demodmap: FD must be a scalar or a 2-element vector"); + endif + else + off = 0; + endif + + if (nargin > 3) + method = varargin{1}; + if (!ischar (method) || (!strcmp (method, "ask") && ... + isempty (findstr (method, "msk")) && isempty (findstr (method, "fsk")) && ... + isempty (findstr (method, "samp")) && !strcmp (method, "psk") && ... + !strcmp (method, "qask") && !strcmp (method, "qam") && ... + !strcmp (method, "qsk") && !strcmp (method, "qask/cir") && ... + !strcmp (method, "qam/cir") && !strcmp (method, "qsk/cir") && ... + !strcmp (method, "qask/arb") && !strcmp (method, "qam/arb") && ... + !strcmp (method, "qsk/arb"))) + error ("demodmap: invalid mapping METHOD '%s'", method); + endif + else + method = "sample"; + endif + + if (! (isreal (off) && off == fix (off) && off >= 0 && off < fs/fd)) + error ("demodmap: OFF must be an integer in the range [0,FS/FD)"); + endif + if (off == 0) + off = round (fs/fd); + endif + + if (min (size (y)) == 1) + y = y(off:round (fs/fd):length (y)); + else + y = y(off:round (fs/fd):size (y, 1),:); + endif + + if (strcmp (method, "ask") || !isempty (findstr (method, "fsk")) || ... + strcmp (method, "psk") || strcmp (method, "qask") || ... + strcmp (method, "qam") || strcmp (method, "qsk")) + if (nargin > 4) + M = varargin{2}; + else + M = 2; + endif + if (!isempty (findstr (method, "fsk")) && (nargin > 5)) + error ("demodmap: too many arguments"); + endif + endif + + z = []; + if (!isempty (findstr (method, "fsk")) || !isempty (findstr (method, "msk"))) + if (findstr (method, "msk")) + if (nargin > 4) + error ("demodmap: too many arguments"); + endif + M = 2; + tone = fd/2; + else + if (nargin > 5) + tone = varargin{3}; + else + tone = fd; + endif + if (nargin > 6) + error ("demodmap: too many arguments"); + endif + endif + + if (findstr (method, "/max")) + if (size (y, 2) != M) + error ("demodmap: Y must be a matrix with M columns for METHOD */max"); + endif + ## We have an M-column maximum from which with pick index of the maximum + ## value in each row as the decoded value + [a, b] = max (y'); + z = (b - 1)'; + else + c = [0:M-1]*tone; + endif + elseif (strcmp (method, "ask")) + if (M/2 == floor (M/2)) + c = [ -2*([M/2:-1:1]-0.5)/(M-1), 2*([1:M/2]-0.5)/(M-1)]; + else + c = [ -2*([floor(M/2):-1:1])/(M-1), 0, 2*([1:floor(M/2)])/(M-1)]; + endif + elseif (strcmp (method, "psk")) + c = apkconst (M, [], []); + elseif (!isempty (findstr (method, "qask")) || ... + !isempty (findstr (method, "qsk")) || ... + !isempty (findstr (method, "qam"))) + if (findstr (method, "/cir")) + nsig = 2; + amp = []; + phs = []; + if (nargin > 4) + nsig = varargin{2}; + if (!isvector (nsig)) + error ("demodmap: NSIG must be a vector of constellation points for METHOD qask/cir"); + endif + endif + if (nargin > 5) + amp = varargin{3}; + endif + if (nargin > 6) + phs = varargin{4}; + endif + c = apkconst (nsig, amp, phs); + M = length (c); + elseif (findstr (method, "/arb")) + if (nargin == 4) + c = qaskenco (2); + elseif (nargin == 5) + c = varargin{2}; + elseif (nargin == 6) + inphase = varargin{2}; + quadr = varargin{3}; + c = inphase + 1i*quadr; + elseif (nargin > 6) + error ("demodmap: too many arguments"); + endif + M = length (c); + else + ## Could do "c = qaskenco (M)", but qaskdeco's speed is not dependent + ## on M, while speed of code below is O(M). + z = qaskdeco (y, M); + endif + endif + + ## Have we decoded yet? If not have a mapping that we can use. + if (isempty (z)) + c = c(:); + z = zeros (size (y)); + if (size (y, 1) == 1) + [a, b] = min (abs (repmat (y(:).', M, 1) - repmat (c, 1, size (y, 2)))); + z = b - 1; + elseif (size (y, 1) == 1) + [a, b] = min (abs (repmat (y(:), M, 1) - repmat (c, 1, size (y, 1)))); + z = (b - 1).'; + else + for i = 1:size (y, 1) + [a, b] = min (abs (repmat (y(i,:), M, 1) - repmat (c, 1, size (y, 2)))); + z(i,:) = b - 1; + endfor + endif + endif + +endfunction + +%% Test input validation +%!error demodmap () +%!error demodmap (1) +%!error demodmap (1, 2) +%!error demodmap (1, 2, 3, "invalid") diff --git a/inst/dpcmdeco.m b/inst/dpcmdeco.m new file mode 100644 index 0000000..29348a3 --- /dev/null +++ b/inst/dpcmdeco.m @@ -0,0 +1,49 @@ +## Copyright (C) 2012 Leonardo Araujo +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{sig} =} dpcmdeco (@var{indx}, @var{codebook}, @var{predictor}) +## Decode using differential pulse code modulation (DPCM). +## +## @table @code +## @item sig = dpcmdeco (indx, codebook, predictor) +## Decode the signal coded by DPCM. +## Use the prediction model and the coded prediction error given by a codebook and +## the index of each sample in this codebook. +## +## @end table +## @seealso{dpcmenco, dpcmopt} +## @end deftypefn + +function sig = dpcmdeco (indx, codebook, predictor) + + if (nargin != 3) + print_usage (); + endif + + quants = codebook(indx+1); + sig = zeros (size (quants)); + for i = 1 : length (sig) + ## signal prediction (convolution of signal and predictor coefficients) + quantization error + sig(i) = sig(max (i - length (predictor) + 1, 1):i) * predictor(end:-1:max (end-i+1, 1))' + quants(i); + endfor + +endfunction + +%% Test input validation +%!error dpcmdeco () +%!error dpcmdeco (1) +%!error dpcmdeco (1, 2) +%!error dpcmdeco (1, 2, 3, 4) diff --git a/inst/dpcmenco.m b/inst/dpcmenco.m new file mode 100644 index 0000000..c9e2a2d --- /dev/null +++ b/inst/dpcmenco.m @@ -0,0 +1,113 @@ +## Copyright (C) 2012 Leonardo Araujo +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{qidx} =} dpcmenco (@var{sig}, @var{codebook}, @var{partition}, @var{predictor}) +## @deftypefnx {Function File} {[@var{qidx}, @var{q}] =} dpcmenco (@var{sig}, @var{codebook}, @var{partition}, @var{predictor}) +## @deftypefnx {Function File} {[@var{qidx}, @var{q}, @var{d}] =} dpcmenco (@dots{}) +## Encode using differential pulse code modulation (DPCM). +## +## @table @code +## @item qidx = dpcmenco (sig, codebook, partition, predictor) +## Determine position of the prediction error in a strictly monotonic table (partition). +## The predictor vector describes a m-th order prediction for the +## output according to the following equation +## y(k) = p(1)sig(k-1) + p(2)sig(k-2) + ... + p(m-1)sig(k-m+1) + p(m)sig(k-m) , +## where the predictor vector is given by +## predictor = [0, p(1), p(2), p(3),..., p(m-1), p(m)]. +## +## @item [qidx, q] = dpcmenco (sig, codebook, partition, predictor) +## Also return the quantized values. +## +## @item [qidx, q, d] = dpcmenco (...) +## Also compute distortion: mean squared distance of original sig from the +## corresponding quantized values. +## +## @end table +## @seealso{dpcmdeco, dpcmopt, quantiz} +## @end deftypefn + +function [indx, quants, distor] = dpcmenco (sig, codebook, partition, predictor) + + if (nargin != 4) + print_usage (); + endif + + y = zeros (size (sig)); + indx = []; quants = []; + for i = 1:length (y) + ## use last predicted value to find the error + y(i) = y(max (i - length (predictor) + 1, 1):i) * predictor(end:-1:max (end-i+1, 1))'; # convolution + e(i) = sig(i) - y(i); # error + [indx(i), quants(i)] = quantiz (e(i), partition, codebook); # quantize the error + y(i) += quants(i); # update prediction value + endfor + + ## compute distortion + if (nargout > 2) + sigq = dpcmdeco (indx, codebook, predictor); + distor = sumsq (sig(:) - sigq(:)) / length (sig); + endif + +endfunction + +%!function y = my_sawtooth (t, width) +%! ## sawtooth function, so not to require the signal package for the demo and test +%! if (nargin == 1) +%! width = 1; +%! endif +%! t = mod (t / (2 * pi), 1); +%! y = zeros (size (t)); +%! if (width != 0) +%! y (t < width) = 2 * t (t < width) / width - 1; +%! endif +%! if (width != 1) +%! y( t >= width) = -2 * (t (t >= width) - width) / (1 - width) + 1; +%! endif +%!endfunction + +%!demo +%! predictor = [0 1]; +%! nbits = 4; +%! delta = 2^(-nbits+1); +%! codebook = [-1+delta/2 : delta : 1-delta/2]; +%! partition = (codebook(1:end-1) + codebook(2:end))/2; +%! t = linspace (0, 2*pi, 128); +%! x = my_sawtooth (2*t, 0.25); +%! [idx, xq, distor] = dpcmenco (x, codebook, partition, predictor); +%! xr = dpcmdeco (idx, codebook, predictor); +%! plot (t, x, 'k--','linewidth',1, t, xr, 'b-','linewidth',1); +%! xlim ([0 2*pi]); +%! xlabel ('t'); ylabel ('x(t)'); +%! legend ('original', 'dpcm'); +%! title ( sprintf ('distortion = %.3f', distor) ); + +%% Test input validation +%!error dpcmenco () +%!error dpcmenco (1) +%!error dpcmenco (1, 2) +%!error dpcmenco (1, 2, 3) +%!error dpcmenco (1, 2, 3, 4, 5) + +%!test +%! predictor = [0 1]; +%! partition = [-0.5, 0, 0.5]; +%! codebook = [-1, -0.25, 0.25, 1]; +%! t = [0:pi/2:2*pi]; +%! x = my_sawtooth(2*t); +%! [idx, qx, distor] = dpcmenco(x, codebook, partition, predictor); +%! assert (idx, [0, 3, 0, 3, 0]) +%! assert (qx, [-1, 1, -1, 1, -1]) +%! assert (distor, 0) diff --git a/inst/dpcmopt.m b/inst/dpcmopt.m new file mode 100644 index 0000000..7033867 --- /dev/null +++ b/inst/dpcmopt.m @@ -0,0 +1,86 @@ +## Copyright (C) 2012 Leonardo Araujo +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{predictor} =} dpcmopt (@var{training_set}, @var{ord}) +## @deftypefnx {Function File} {[@var{predictor}, @var{partition}, @var{codebook}] =} dpcmopt (@var{training_set}, @var{ord}, @var{cb}) +## Optimize the DPCM parameters and codebook. +## +## It uses the Levinson-Durbin algorithm to find the all-pole IIR filter +## using the autocorrelation sequence. After the best predictor is found, +## it uses the Lloyds algorithm to find the best codebook and partition +## for the interval. +## +## @table @code +## @item predictor = dpcmopt (training_set, ord) +## Optimize the DPCM parameters using the Levinson-Durbin algorithm. +## The predictor vector describes a m-th order prediction for the +## output according to the following equation +## y(k) = p(1)sig(k-1) + p(2)sig(k-2) + ... + p(m-1)sig(k-m+1) + p(m)sig(k-m) +## where the predictor vector is given by +## predictor = [0, p(1), p(2), p(3),..., p(m-1), p(m)]. +## +## training_set is the training data used to find the best predictor. +## +## ord is the order of the desired prediction model. +## +## @item [predictor, partition, codebook] = dpcmopt (training_set,ord,cb) +## Optimize the DPCM parameters and also uses the Lloyds algorithm to find +## the best codebook and partition for the given training signal. +## +## cb might be the initial codebook used by Lloyds algorithm or +## the length of the desired codebook. +## +## @end table +## @seealso{dpcmenco, dpcmdeco, levinson, lloyds} +## @end deftypefn + +function [predictor, partition, codebook] = dpcmopt (training_set, ord, cb) + + if (nargin < 2 || nargin > 3) + print_usage (); + endif + + training_set = training_set(:); + L = length (training_set); + corr_tr = xcorr (training_set'); # autocorrelation + ncorr_tr = corr_tr(L:L+ord+1) ./ (L - [1:ord+2]); # normalize + ## use Levinson-Durbin recursion to solve the Yule-Walker equations + a = levinson (ncorr_tr, ord); + predictor = [0 - a(2:end)]; + + if (nargin > 2 && nargout > 1) + ## predictive error + e = []; + for i = ord+1 : L + e(i-ord) = training_set(i) - fliplr (predictor) * training_set(i-ord:i); + endfor + + ## find the best codebook and partition table + if (length (cb) == 1) + len = cb; + [partition, codebook] = lloyds (e, len); + else + initcodebook = cb; + [partition, codebook] = lloyds (e, initcodebook); + endif + endif + +endfunction + +%% Test input validation +%!error dpcmopt () +%!error dpcmopt (1) +%!error dpcmopt (1, 2, 3, 4) diff --git a/inst/egolaydec.m b/inst/egolaydec.m new file mode 100644 index 0000000..dd393f2 --- /dev/null +++ b/inst/egolaydec.m @@ -0,0 +1,116 @@ +## Copyright (C) 2007 Muthiah Annamalai +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {[@var{C}, @var{err}] =} egolaydec (@var{R}) +## Decode Extended Golay code. +## +## Given @var{R}, the received Extended Golay code, this function tries to +## decode it using the Extended Golay code parity check matrix. +## Extended Golay code (24,12) which can correct up to 3 errors. +## +## The received code @var{R}, needs to be of length Nx24, for encoding. We can +## decode several codes at once, if they are stacked as a matrix of 24 columns, +## each code in a separate row. +## +## The generator used in here is same as obtained from the function +## @code{egolaygen}. +## +## The function returns @var{C}, the error-corrected code word from the received +## word. If decoding failed, @var{err} value is 1, otherwise it is 0. +## +## Extended Golay code (24,12) which can correct up to 3 +## errors. Decoding algorithm follows from Lin & Costello. +## +## Ref: Lin & Costello, pg 128, Ch4, "Error Control Coding", 2nd ed, Pearson. +## +## @example +## @group +## msg = rand (10, 12) > 0.5; +## c1 = egolayenc (msg); +## c1(:,1) = mod (c1(:,1) + 1, 2) +## c2 = egolaydec (c1) +## @end group +## @end example +## +## @seealso{egolaygen, egolayenc} +## @end deftypefn + +function [C, dec_error] = egolaydec (R) + + if (nargin != 1) + print_usage (); + elseif (columns (R) != 24) + error ("egolaydec: R must be a matrix with 24 columns"); + endif + + dec_error = []; + [~, P] = egolaygen (); + H = [eye(12); P]; # parity check matrix transpose + C = zeros (size (R)); + + for rspn = 1:rows (R) + RR = R(rspn,:); + S = mod (RR*H, 2); + wt = sum (S); + done = 0; + E = [S, zeros(1, 12)]; + if (wt <= 3) + E = [S, zeros(1, 12)]; + done = 1; + else + SP = mod (repmat (S, [12, 1]) + P, 2); + idx = find (sum (SP, 2) <= 2); + if (idx) + idx = idx(1); # pick first of matches. + Ui = zeros (1, 12); + Ui(idx) = 1; + E = [SP(idx, :), Ui]; + done = 1; + endif + endif + + if (!done) + X = mod (S*P, 2); + wt = sum (X); + if (wt == 2 || wt == 3) + E = [zeros(1, 12), X]; + done = 1; + else + SP = mod (repmat (X, [12, 1]) + P, 2); + idx = find (sum (SP, 2) == 2); + if (idx) + idx = idx(1); + Ui = zeros (1, 12); + Ui(idx) = 1; + E = [Ui, SP(idx, :)]; + done = 1; + endif + endif + endif + + dec_error = [dec_error; 1-done]; + C(rspn, :) = mod (E+RR, 2); + endfor + +endfunction + +%!assert (egolaydec ([1 1 1 zeros(1, 21)]), zeros (1, 24)) +%!assert (egolaydec ([1 0 1 zeros(1, 20) 1]), zeros (1, 24)) + +%% Test input validation +%!error egolaydec () +%!error egolaydec (1) +%!error egolaydec (1, 2) diff --git a/inst/egolayenc.m b/inst/egolayenc.m new file mode 100644 index 0000000..5ab63cb --- /dev/null +++ b/inst/egolayenc.m @@ -0,0 +1,71 @@ +## Copyright (C) 2007 Muthiah Annamalai +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{C} =} egolayenc (@var{M}) +## Encode with Extended Golay code. +## +## The message @var{M}, needs to be of size Nx12, for encoding. +## We can encode several messages, into codes at once, if they +## are stacked in the order suggested. +## +## The generator used in here is same as obtained from the +## function @code{egolaygen}. Extended Golay code (24,12) which can correct +## up to 3 errors. +## +## @example +## @group +## msg = rand (10, 12) > 0.5; +## c = egolayenc (msg) +## @end group +## @end example +## +## @seealso{egolaygen, egolaydec} +## @end deftypefn + +function C = egolayenc (M) + + if (nargin != 1) + print_usage (); + elseif (columns (M) != 12) + error ("egolayenc: M must be a matrix with 12 columns"); + endif + + G = egolaygen (); # generator + + C = mod (M * G, 2); + +endfunction + +%% Test input validation +%!error egolayenc () +%!error egolayenc (1) +%!error egolayenc (1, 2) + +%%test encryption-decryption and robustness to error +%!test +%! x = [1 1 0 0 1 1 0 0 0 0 1 0; 1 1 1 0 1 1 1 0 0 0 1 1]; +%! y = egolayenc (x); +%! err = zeros(2, 24); +%! err(1, [4 10 12]) = 1; #should be able to correct any 3 errors per column +%! err(2, [2 3 13]) = 1; +%! y1 = xor (y, err); +%! [xb, err0] = egolaydec (y); +%! [x1, err1] = egolaydec (y1); +%! assert (y, [1 1 1 0 0 0 1 1 0 0 1 1 1 1 0 0 1 1 0 0 0 0 1 0; 1 0 0 1 0 0 1 1 1 1 1 1 1 1 1 0 1 1 1 0 0 0 1 1]) +%! assert (xb(:, 13:24), x) +%! assert (x1(:, 13:24), x) +%! assert (err0, [0; 0]) +%! assert (err1, [0; 0]) diff --git a/inst/egolaygen.m b/inst/egolaygen.m new file mode 100644 index 0000000..02d35a0 --- /dev/null +++ b/inst/egolaygen.m @@ -0,0 +1,57 @@ +## Copyright (C) 2007 Muthiah Annamalai +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {[@var{G}, @var{P}] =} egolaygen () +## Extended Golay code generator matrix. +## +## Returns @var{G}, the Extended Golay code (24,12) generator matrix, +## which can correct up to 3 errors. @var{P} is the parity +## check matrix, for this code. +## +## @seealso{egolaydec, egolayenc} +## @end deftypefn + +function [G, P] = egolaygen () + + if (nargin != 0) + print_usage (); + endif + + I = eye (12); + P = [1 0 0 0 1 1 1 0 1 1 0 1; + 0 0 0 1 1 1 0 1 1 0 1 1; + 0 0 1 1 1 0 1 1 0 1 0 1; + 0 1 1 1 0 1 1 0 1 0 0 1; + 1 1 1 0 1 1 0 1 0 0 0 1; + 1 1 0 1 1 0 1 0 0 0 1 1; + 1 0 1 1 0 1 0 0 0 1 1 1; + 0 1 1 0 1 0 0 0 1 1 1 1; + 1 1 0 1 0 0 0 1 1 1 0 1; + 1 0 1 0 0 0 1 1 1 0 1 1; + 0 1 0 0 0 1 1 1 0 1 1 1; + 1 1 1 1 1 1 1 1 1 1 1 0;]; + G = [P I]; # generator. + +endfunction + +%!test +%! g = egolaygen (); +%! assert (size (g), [12, 24]) +%! assert (g(:,13:end), eye (12)) +%! assert (sum (g(:,1:12)), [7*ones(1, 11), 11]) + +%% Test input validation +%!error egolaygen (1) diff --git a/inst/encode.m b/inst/encode.m new file mode 100644 index 0000000..d7ff803 --- /dev/null +++ b/inst/encode.m @@ -0,0 +1,226 @@ +## Copyright (C) 2003 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{code} =} encode (@var{msg}, @var{n}, @var{k}) +## @deftypefnx {Function File} {@var{code} =} encode (@var{msg}, @var{n}, @var{k}, @var{typ}) +## @deftypefnx {Function File} {@var{code} =} encode (@var{msg}, @var{n}, @var{k}, @var{typ}, @var{opt}) +## @deftypefnx {Function File} {[@var{code}, @var{added}] =} encode (@dots{}) +## +## Top level block encoder. This function makes use of the lower level +## functions such as @code{cyclpoly}, @code{cyclgen}, @code{hammgen}, and +## @code{bchenco}. The message to code is pass in @var{msg}, the +## codeword length is @var{n} and the message length is @var{k}. This +## function is used to encode messages using either: +## +## @table @asis +## @item A [n,k] linear block code defined by a generator matrix +## @item A [n,k] cyclic code defined by a generator polynomial +## @item A [n,k] Hamming code defined by a primitive polynomial +## @item A [n,k] BCH code code defined by a generator polynomial +## @end table +## +## The type of coding to use is defined by the variable @var{typ}. This +## variable is a string taking one of the values +## +## @table @code +## @item "linear" +## @itemx "linear/binary" +## A linear block code is assumed with the coded message @var{code} being in +## a binary format. In this case the argument @var{opt} is the generator +## matrix, and is required. +## @item "cyclic" +## @itemx "cyclic/binary" +## A cyclic code is assumed with the coded message @var{code} being in a +## binary format. The generator polynomial to use can be defined in @var{opt}. +## The default generator polynomial to use will be +## @code{cyclpoly (@var{n}, @var{k})} +## @item "hamming" +## @itemx "hamming/binary" +## A Hamming code is assumed with the coded message @var{code} being in a +## binary format. In this case @var{n} must be of an integer of the form +## @code{2^@var{m}-1}, where @var{m} is an integer. In addition @var{k} +## must be @code{@var{n}-@var{m}}. The primitive polynomial to use can +## be defined in @var{opt}. The default primitive polynomial to use is +## the same as defined by @code{hammgen}. +## @item "bch" +## @itemx "bch/binary" +## A BCH code is assumed with the coded message @var{code} being in a binary +## format. The generator polynomial to use can be defined in @var{opt}. +## The default generator polynomial to use will be +## @code{bchpoly (@var{n}, @var{k})} +## @end table +## +## In addition the argument "binary" above can be replaced with "decimal", +## in which case the message is assumed to be a decimal vector, with each +## value representing a symbol to be coded. The binary format can be in two +## forms +## +## @table @code +## @item An @var{x}-by-@var{k} matrix +## Each row of this matrix represents a symbol to be coded +## @item A vector +## The symbols are created from groups of @var{k} elements of this vector. +## If the vector length is not divisible by @var{k}, then zeros are added +## and the number of zeros added is returned in @var{added}. +## @end table +## +## It should be noted that all internal calculations are performed in the +## binary format. Therefore for large values of @var{n}, it is preferable +## to use the binary format to pass the messages to avoid possible rounding +## errors. Additionally, if repeated calls to @code{encode} will be performed, +## it is often faster to create a generator matrix externally with the +## functions @code{hammgen} or @code{cyclgen}, rather than let @code{encode} +## recalculate this matrix at each iteration. In this case @var{typ} should +## be "linear". The exception to this case is BCH codes, whose encoder +## is implemented directly from the polynomial and is significantly faster. +## +## @seealso{decode, cyclgen, cyclpoly, hammgen, bchenco, bchpoly} +## @end deftypefn + +function [code, added] = encode (msg, n, k, typ, opt) + + if (nargin < 3 || nargin > 5) + print_usage (); + endif + + if (! (isscalar (n) && n == fix (n) && n >= 3)) + error ("encode: N must be an integer greater than 3"); + endif + + if (! (isscalar (k) && k == fix (k) && k <= n)) + error ("encode: K must be an integer less than N"); + endif + + if (nargin > 3) + if (!ischar (typ)) + error ("encode: TYP must be a string"); + else + ## Why the hell did matlab decide on such an ugly way of passing 2 args! + if (strcmp (typ, "linear") || strcmp (typ, "linear/binary")) + coding = "linear"; + msgtyp = "binary"; + elseif (strcmp (typ, "linear/decimal")) + coding = "linear"; + msgtyp = "decimal"; + elseif (strcmp (typ, "cyclic") || strcmp (typ, "cyclic/binary")) + coding = "cyclic"; + msgtyp = "binary"; + elseif (strcmp (typ, "cyclic/decimal")) + coding = "cyclic"; + msgtyp = "decimal"; + elseif (strcmp (typ, "bch") || strcmp (typ, "bch/binary")) + coding = "bch"; + msgtyp = "binary"; + elseif (strcmp (typ, "bch/decimal")) + coding = "bch"; + msgtyp = "decimal"; + elseif (strcmp (typ, "hamming") || strcmp (typ, "hamming/binary")) + coding = "hamming"; + msgtyp = "binary"; + elseif (strcmp (typ, "hamming/decimal")) + coding = "hamming"; + msgtyp = "decimal"; + else + error ("encode: invalid coding and/or message TYP '%s'", typ); + endif + endif + else + coding = "hamming"; + msgtyp = "binary"; + endif + + added = 0; + if (strcmp (msgtyp, "binary")) + vecttyp = 0; + if (max (msg(:)) > 1 || min (msg(:)) < 0) + error ("encode: MSG must be a binary matrix"); + endif + [ncodewords, k2] = size (msg); + len = k2*ncodewords; + if (min (k2, ncodewords) == 1) + vecttyp = 1; + msg = vec2mat (msg, k); + ncodewords = size (msg, 1); + elseif (k2 != k) + error ("encode: MSG must be a matrix with K columns"); + endif + else + if (!isvector (msg)) + error ("encode: decimal MSG type must be a vector"); + endif + if (max (msg) > 2^k-1 || min (msg) < 0) + error ("encode: all elements of MSG must be in the range [0,2^K-1]"); + endif + ncodewords = length (msg); + msg = de2bi (msg(:), k); + endif + + if (strcmp (coding, "bch")) + if (nargin > 4) + code = bchenco (msg, n, k, opt); + else + code = bchenco (msg, n, k); + endif + else + if (strcmp (coding, "linear")) + if (nargin > 4) + gen = opt; + if ((size (gen, 1) != k) || (size (gen, 2) != n)) + error ("encode: generator matrix must be of size KxN"); + endif + else + error ("encode: linear coding requires a generator matrix"); + endif + elseif (strcmp (coding, "cyclic")) + if (nargin > 4) + [par, gen] = cyclgen (n, opt); + else + [par, gen] = cyclgen (n, cyclpoly (n, k)); + endif + else + m = log2 (n + 1); + if (! (m == fix (m) && m >= 3 && m <= 16)) + error ("encode: N must be equal to 2^M-1 for integer M in the range [3,16]"); + endif + if (k != (n-m)) + error ("encode: K must be equal to N-M for Hamming coder"); + endif + if (nargin > 4) + [par, gen] = hammgen (m, opt); + else + [par, gen] = hammgen (m); + endif + endif + code = mod (msg * gen, 2); + endif + + if (strcmp (msgtyp, "binary") && vecttyp == 1) + code = code'; + code = code(:); + elseif (strcmp (msgtyp, "decimal")) + code = bi2de (code); + endif + +endfunction + +%% Test input validation +%!error encode () +%!error encode (1) +%!error encode (1, 2) +%!error encode (1, 2, 3, 4, 5, 6) +%!error decode (1, 2, 3) +%!error decode (1, 5, 6) +%!error decode (1, 5, 3, "invalid") diff --git a/inst/eyediagram.m b/inst/eyediagram.m new file mode 100644 index 0000000..8966fbd --- /dev/null +++ b/inst/eyediagram.m @@ -0,0 +1,210 @@ +## Copyright (C) 2003 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} eyediagram (@var{x}, @var{n}) +## @deftypefnx {Function File} {} eyediagram (@var{x}, @var{n}, @var{per}) +## @deftypefnx {Function File} {} eyediagram (@var{x}, @var{n}, @var{per}, @var{off}) +## @deftypefnx {Function File} {} eyediagram (@var{x}, @var{n}, @var{per}, @var{off}, @var{str}) +## @deftypefnx {Function File} {} eyediagram (@var{x}, @var{n}, @var{per}, @var{off}, @var{str}, @var{h}) +## @deftypefnx {Function File} {@var{h} =} eyediagram (@dots{}) +## +## Plot the eye-diagram of a signal. The signal @var{x} can be either in one +## of three forms +## +## @table @asis +## @item A real vector +## In this case the signal is assumed to be real and represented by the vector +## @var{x}. A single eye-diagram representing this signal is plotted. +## @item A complex vector +## In this case the in-phase and quadrature components of the signal are +## plotted separately. +## @item A matrix with two columns +## In this case the first column represents the in-phase and the second the +## quadrature components of a complex signal. +## @end table +## +## Each line of the eye-diagram has @var{n} elements and the period is assumed +## to be given by @var{per}. The time axis is then [-@var{per}/2 @var{per}/2]. +## By default @var{per} is 1. +## +## By default the signal is assumed to start at -@var{per}/2. This can be +## overridden by the @var{off} variable, which gives the number of samples +## to delay the signal. +## +## The string @var{str} is a plot style string (example "r+"), +## and by default is the default gnuplot line style. +## +## The figure handle to use can be defined by @var{h}. If @var{h} is not +## given, then the next available figure handle is used. The figure handle +## used in returned on @var{hout}. +## @seealso{scatterplot} +## @end deftypefn + +function varargout = eyediagram (x, n, _per, _off, str, h) + + if (nargin < 2 || nargin > 6) + print_usage (); + endif + + if (isreal (x)) + if (min (size (x)) == 1) + signal = "real"; + xr = x(:); + elseif (size (x, 2) == 2) + signal = "complex"; + xr = x(:,1); + xi = x(:,2); + else + error ("eyediagram: real X must be a vector or a 2-column matrix"); + endif + else + signal = "complex"; + if (min (size (x)) != 1) + error ("eyediagram: complex X must be a vector"); + endif + xr = real (x(:)); + xi = imag (x(:)); + endif + + if (!length (xr)) + error ("eyediagram: X must not be empty"); + endif + + if (! (isscalar (n) && isreal (n) && n == fix (n) && n > 0)) + error ("eyediagram: N must be a positive integer"); + endif + + if (nargin > 2) + if (isempty (_per)) + per = 1; + elseif (isscalar (_per) && isreal (_per)) + per = _per; + else + error ("eyediagram: PER must be a real scalar"); + endif + else + per = 1; + endif + + if (nargin > 3) + if (isempty (_off)) + off = 0; + elseif (! (isscalar (_off) && isreal (_off) && _off == fix (_off) + && _off >= 0 && _off < n)) + error ("eyediagram: OFF must be an integer in the range [0,N-1]"); + else + off = _off; + endif + else + off = 0; + endif + + if (nargin > 4) + if (isempty (str)) + fmt = "-"; + elseif (ischar (str)) + fmt = str; + else + error ("eyediagram: STR must be a string"); + endif + else + fmt = "-"; + endif + + if (nargin > 5) + if (isempty (h)) + hout = figure (); + elseif (isfigure (h) && strcmp (get (h, "tag"), "eyediagram")) + hout = h; + else + error ("eyediagram: H must be an eyediagram figure handle"); + endif + else + hout = figure (); + endif + set (hout, "tag", "eyediagram"); + set (hout, "name", "Eye Diagram"); + set (0, "currentfigure", hout); + + horiz = (per*[0:n]/n - per/2)'; + if (n/2 != fix (n/2)) + horiz = horiz - per / n / 2; + endif + lx = length (xr); + off = mod (off + ceil (n/2), n); + Nn = ceil ((off + lx) / n); + post = Nn*n - off - lx; + xr = reshape ([NaN * ones(off, 1); xr; NaN * ones(post, 1)], n, Nn); + xr = [xr ; [xr(1,2:end), NaN]]; + xr = [xr; NaN * ones(1, Nn)]; + if (all (isnan (xr(2:end,end)))) + xr(:,end) = []; + horiz = [repmat(horiz(1:n+1), 1, Nn-1); NaN * ones(1, Nn - 1)](:); + else + horiz = [repmat(horiz(1:n+1), 1, Nn); NaN * ones(1, Nn)](:); + endif + + if (strcmp(signal,"complex")) + xi = reshape([NaN * ones(off,1); xi; NaN * ones(post, 1)], n, Nn); + xi = [xi ; [xi(1,2:end), NaN]]; + xi = [xi; NaN * ones(1, Nn)]; + if (all (isnan (xi(2:end,end)))) + xi(:,end) = []; + endif + endif + + if (strcmp (signal, "complex")) + subplot (2, 1, 1); + plot (horiz, xr(:), fmt); + xlim ([horiz(1), horiz(end-1)]); + title ("Eye-diagram for in-phase signal"); + xlabel ("Time"); + ylabel ("Amplitude"); + subplot (2, 1, 2); + plot (horiz, xi(:), fmt); + xlim ([horiz(1), horiz(end-1)]); + title ("Eye-diagram for quadrature signal"); + xlabel ("Time"); + ylabel ("Amplitude"); + else + plot (horiz, xr(:), fmt); + xlim ([horiz(1), horiz(end-1)]); + title ("Eye-diagram for signal"); + xlabel ("Time"); + ylabel ("Amplitude"); + endif + + if (nargout > 0) + varargout{1} = hout; + endif + +endfunction + +%!demo +%! n = 50; +%! ovsp = 50; +%! x = 1:n; +%! xi = [1:1/ovsp:n-0.1]; +%! y = randsrc (1, n, [1 + i, 1 - i, -1 - i, -1 + i]); +%! yi = interp1 (x, y, xi); +%! noisy = awgn (yi, 15, "measured"); +%! eyediagram (noisy, ovsp); + +%% Test input validation +%!error eyediagram () +%!error eyediagram (1) +%!error eyediagram (1, 2, 3, 4, 5, 6) +%!error eyediagram (1, -1) diff --git a/inst/fibodeco.m b/inst/fibodeco.m new file mode 100644 index 0000000..d0001d7 --- /dev/null +++ b/inst/fibodeco.m @@ -0,0 +1,85 @@ +## Copyright (C) 2006 Muthiah Annamalai +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} fibodeco (@var{code}) +## +## Returns the decoded Fibonacci value from the binary vectors @var{code}. +## Universal codes like Fibonacci codes have a useful synchronization property, +## only for 255 maximum value we have designed these routines. We assume +## user has partitioned the code into several unique segments based on +## the suffix property of unique strings "11" and we just decode the +## parts. Partitioning the stream is as simple as identifying the +## "11" pairs that occur, at the terminating ends. This system implements +## the standard binary Fibonacci codes, which means that row vectors +## can only contain 0 or 1. Ref: @url{http://en.wikipedia.org/wiki/Fibonacci_coding} +## +## @example +## @group +## fibodeco (@{[0 1 0 0 1 1]@}) +## @result{} 10 +## fibodeco (@{[1 1], [0 1 1], [0 0 1 1], [1 0 1 1]@}) +## @result{} [1, 2, 3, 4] +## @end group +## @end example +## @seealso{fiboenco} +## @end deftypefn + +function num = fibodeco (code) + + ## + ## generate fibonacci series table. + ## + ## f(1)=1; + ## f(2)=1; + ## + ## while ((f(end-1)+f(end)) < 256) + ## val=(f(end-1)+f(end)); + ## f=[f val]; + ## endwhile + ## f=f(2:end); + ## + ## all numbers terminate with 1 except 0 itself. + ## + ## + ## f= [75025 46368 28657 17711 10946 6765 4181 2584 \ + ## 1597 987 610 377 233 144 89 55 \ + ## 34 21 13 8 5 3 2 1]; + ## + ## f= [ 233 144 89 55 34 21 13 8 5 3 2 1]; + + f = [1 2 3 5 8 13 21 34 55 89 144 233]; + L_C = length (code); + + if (nargin != 1) + print_usage (); + endif + + for j = 1:L_C + word = code{j}; + ## discard the terminating 1. + word = word(1:end-1); + L = length (word); + num(j) = sum (word.*f(1:L)); + endfor + +endfunction + +%!assert (fibodeco ({[1 1], [0 1 1], [0 0 1 1], [1 0 1 1]}), [1:4]) +%!assert (fibodeco ({[0 1 0 0 1 1]}), 10) + +%% Test input validation +%!error fibodeco () +%!error fibodeco (1, 2) diff --git a/inst/fiboenco.m b/inst/fiboenco.m new file mode 100644 index 0000000..31913bc --- /dev/null +++ b/inst/fiboenco.m @@ -0,0 +1,99 @@ +## Copyright (C) 2006 Muthiah Annamalai +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} fiboenco (@var{num}) +## +## Returns the cell-array of encoded Fibonacci value from the column vectors @var{num}. +## Universal codes like Fibonacci codes have a useful synchronization +## property, only for 255 maximum value we have designed these routines. We assume +## user has partitioned the code into several unique segments based on +## the suffix property of unique elements [1 1] and we just decode the +## parts. Partitioning the stream is as simple as identifying the [1 1] +## pairs that occur, at the terminating ends. This system implements +## the standard binary Fibonacci codes, which means that row vectors +## can only contain 0 or 1. Ref: http://en.wikipedia.org/wiki/Fibonacci_coding +## Ugly O(k.N^2) encoder.Ref: Wikipedia article accessed March, 2006. +## @url{http://en.wikipedia.org/wiki/Fibonacci_coding}, UCI Data Compression +## Book, @url{http://www.ics.uci.edu/~dan/pubs/DC-Sec3.html}, (accessed +## October 2006) +## +## @example +## @group +## fiboenco (10) +## @result{} @{[ 0 1 0 0 1 1]@} +## fiboenco (1:4) +## @result{} @{[1 1], [0 1 1], [0 0 1 1], [1 0 1 1]@} +## @end group +## @end example +## @seealso{fibodeco} +## @end deftypefn + +function op_num = fiboenco (num) + + ## + ## generate fibonacci series table. + ## + ## f(1)=1; + ## f(2)=1; + ## + ## while ((f(end-1)+f(end)) < 256) + ## val=(f(end-1)+f(end)); + ## f=[f val]; + ## endwhile + ## f=sort(f(2:end),"descend"); + ## + + ## f= [75025 46368 28657 17711 10946 6765 4181 2584 \ + ## 1597 987 610 377 233 144 89 55 \ + ## 34 21 13 8 5 3 2 1]; + + if (nargin != 1 || min (num) <= 0 || max (num) > 608) + print_usage (); + endif + f = [233 144 89 55 34 21 13 8 5 3 2 1]; + + onum = num; + LEN_F = length (f); + LEN_N = length (num); + + for j = 1:LEN_N + N = num(j); + rval = []; + + ## create Fibonacci encoding of a number + for i = (find (f <= N, 1, "first")):LEN_F + if (N >= f(i)) + N = N-f(i); + rval = [1 rval]; + else + rval = [0 rval]; + endif + endfor + op_num{j} = [rval 1]; + endfor + +endfunction + +%!assert (fiboenco (10), {[ 0 1 0 0 1 1]}) +%!assert (fiboenco (11), {[ 0 0 1 0 1 1]}) +%!assert (fiboenco (1:4), {[1 1], [0 1 1], [0 0 1 1], [1 0 1 1]}) +%!assert (fibodeco (fiboenco (1:600)), [1:600]) + +%% Test input validation +%!error fiboenco () +%!error fiboenco (1, 2) +%!error fiboenco (0) +%!error fiboenco (1000) diff --git a/inst/fibosplitstream.m b/inst/fibosplitstream.m new file mode 100644 index 0000000..f02d682 --- /dev/null +++ b/inst/fibosplitstream.m @@ -0,0 +1,82 @@ +## Copyright (C) 2006 Muthiah Annamalai +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} fibosplitstream (@var{code}) +## +## Returns the split data stream at the word boundaries. +## Assuming the stream was originally encoded using @code{fiboenco} +## and this routine splits the stream at the points where "11" +## occur together & gives us the code-words which +## can later be decoded from the @code{fibodeco} This however doesn't +## mean that we intend to verify if all the codewords are correct, +## and in fact the last symbol in the return list can or can not be +## a valid codeword. +## +## A example use of @code{fibosplitstream} would be +## @example +## @group +## fibodeco (fibosplitstream ([fiboenco(randint (1, 100, [0, 255]))@{:@}])) +## fibodeco (fibosplitstream ([fiboenco(1:10)@{:@}])) +## @end group +## @end example +## @seealso{fiboenco, fibodeco} +## @end deftypefn + +function symbols = fibosplitstream (stream) + + if (nargin != 1) + print_usage (); + endif + + symbols = {}; + itr = 1; + L = length (stream); + + ## + ## Plain & Simple Algorithm. O(N) + ## Walk till marker "11" or find it. + ## Then split & save. A little tricky to + ## handle the edge case_ without tripping over. + ## + idx = []; + mark = 1; + prev_bit = stream(1); + just_decoded = 0; + + for i = 2:L + if (!just_decoded && (stream(i)+prev_bit) == 2) + symbols{itr} = [stream(mark:i)]; + mark = i + 1; + prev_bit = 0; + just_decoded = 1; + itr = itr+1; + else + prev_bit = stream(i); + just_decoded = 0; + endif + + endfor + if (mark < L) + symbols{itr} = stream(mark:end); + endif + +endfunction + +%!assert (fibodeco (fibosplitstream ([fiboenco(1:10){:}])), [1:10]) + +%% Test input validation +%!error fibosplitstream () +%!error fibosplitstream (1, 2) diff --git a/inst/finddelay.m b/inst/finddelay.m new file mode 100644 index 0000000..c336b56 --- /dev/null +++ b/inst/finddelay.m @@ -0,0 +1,84 @@ +## Copyright (C) 2021 The Octave Project Developers +## Copyright (C) 2006 Robert T. Short +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{d} =} finddelay (@var{x}, @var{y}) +## Estimate the delay between times series @var{x} and time series @var{y} by +## correlating and finding the peak. The index of the peak correlation +## is returned in @var{d}. +## +## Inputs: +## @itemize +## @var{x}, @var{y}: signals +## @end itemize +## +## Output: +## @itemize +## @var{d}: The delay between the two signals +## @end itemize +## +## Example: +## @example +## x = [0, 0, 1, 2, 3]; +## y = [1, 2, 3]; +## d = finddelay (x, y) +## d = -2 +## @end example +## @seealso{xcorr} +## @end deftypefn + +function d = finddelay (x, y) + + ## Check arguments and set defaults. + + if (nargin != 2) + print_usage(); + endif + + [R, lag] = xcorr (x, y); + d = -(lag(R == max (R))); + + if (abs (d) == 0) #TODO better method for L52 so no -0 + d = 0; + endif + + d = min (d); + + ## zLs method passes 2 of 4 tests + ## [R, lag] = xcorr(x, y); + ## [a b] = max(R); + ## D = abs (b - length(x)); + + ## Robert Short method passes 1 of 4 tests + ## x = x(:); + ## y = y(:); + ## N1 = length (x); % total data length + ## N2 = length (y); % + ## c = zeros (N2- N1 + 1, 1); + + ## for (idx = 1: N2 - N1) + ## c(idx) = x'*y(idx: idx + N1 - 1) / N1; + ## end + ## [m, d] = max (abs (c)); + +endfunction +%!test +%! d = finddelay([0, 0, 1, 2, 3], [1, 2, 3]); +%! assert (d, -2) + +%!test +%! d = finddelay([1, 2, 3], [0, 0, 1, 2, 3]); +%! assert (d, 2) \ No newline at end of file diff --git a/inst/fmdemod.m b/inst/fmdemod.m new file mode 100644 index 0000000..94b5b8b --- /dev/null +++ b/inst/fmdemod.m @@ -0,0 +1,63 @@ +## Copyright (C) 2021 The Octave Project Developers +## Copyright (C) 2007 Sylvain Pelissier +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{m} =} fmdemod (@var{s}, @var{fc}, @var{fs}) +## Creates the FM demodulation of the signal @var{s} +## sampled at frequency @var{fs} with carrier frequency @var{fc}. +## +## Inputs: +## @itemize +## @item +## @var{s}: FM modulated signal +## +## @item +## @var{fc}: carrier frequency +## +## @item +## @var{fs}: sampling frequency +## @end itemize +## +## Output: +## @itemize +## @var{m}: FM demodulation of the signal +## @end itemize +## +## @seealso{ammod, amdemod, fmmod} +## @end deftypefn + +function m = fmdemod (s, fc, fs) + + if (nargin != 3) + print_usage (); + endif + + if (fs < 2 .* fc) + error ("fmdemod: fs is too small must be at least 2 * fc") + endif + + ds = diff (s); + m = amdemod (abs (ds), fc, fs); + +endfunction + +%% Test input validation +%!error fmdemod () +%!error fmdemod (1) +%!error fmdemod (1, 2) +%!error fmdemod (1, 2, 3, 4) + +%!error fmdemod (pi/2, 100, 10) diff --git a/inst/fmmod.m b/inst/fmmod.m new file mode 100644 index 0000000..59802f0 --- /dev/null +++ b/inst/fmmod.m @@ -0,0 +1,92 @@ +## Copyright (C) 2021 The Octave Project Developers +## Copyright (C) 2015 Francisco Albani +## Copyright (C) 2007 Sylvain Pelissier +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{s} =} fmmod (@var{m}, @var{fc}, @var{fs}, @var{freqdev}) +## Creates the FM modulation @var{s} of the message signal @var{m} with carrier frequency @var{fc}. +## +## Inputs: +## @itemize +## @item +## @var{m}: sinusoidal message signal +## +## @item +## @var{fc}: carrier frequency +## +## @item +## @var{fs}: sampling frequency +## +## @item +## @var{freqdev}: maximum absolute frequency deviation, assuming @var{m} is in [-1:1]. +## @end itemize +## +## Output: +## @itemize +## @var{s}: The FM modulation of @var{m} +## @end itemize +## +## Demo +## @example +## demo fmmod +## @end example +## @seealso{ammod, fmdemod, amdemod} +## @end deftypefn + +function s = fmmod (m, fc, fs, freqdev) + + if (nargin < 4) + print_usage (); + endif + + l = length (m); + t = 0: 1 ./ fs: (l .- 1) ./ fs; + int_m = cumsum (m) ./ fs; + + s = cos (2 .* pi .* fc .* t .+ 2 .* pi .* freqdev .* int_m); + +endfunction + +## Test input validation +%!error fmmod () +%!error fmmod (1) +%!error fmmod (1, 2) + +## From https://www.geeksforgeeks.org/frequency-modulation-fm-using-matlab/ +%!demo +%! ## Sampling Frequency +%! fs = 400; +%! +%! ## Carrier Frequency +%! fc = 200; +%! +%! ## Time Duration +%! time = (0: 1 ./ fs:0.2)'; +%! +%! ## Create two sinusoidal signals with frequencies 30 Hz and 60 Hz +%! x = sin (2 .* pi .* 30 .* time) .+ 2 .* sin (2 .* pi .* 60 .* time); +%! +%! ## Frequency Deviation +%! fDev = 50; +%! +%! ## Frequency modulate x +%! y = fmmod (x, fc, fs, fDev); +%! +%! ## plotting +%! plot (time, x, 'r', time, y, 'b--') +%! xlabel ('Time (s)') +%! ylabel ('Amplitude') +%! legend ('Original Signal','Modulated Signal') \ No newline at end of file diff --git a/inst/gen2par.m b/inst/gen2par.m new file mode 100644 index 0000000..cf2e35a --- /dev/null +++ b/inst/gen2par.m @@ -0,0 +1,55 @@ +## Copyright (C) 2003 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{par} =} gen2par (@var{gen}) +## @deftypefnx {Function File} {@var{gen} =} gen2par (@var{par}) +## +## Converts binary generator matrix @var{gen} to the parity check matrix +## @var{par} and visa-versa. The input matrix must be in standard form. +## That is a generator matrix must be k-by-n and in the form [eye(k) P] +## or [P eye(k)], and the parity matrix must be (n-k)-by-n and of the +## form [eye(n-k) P'] or [P' eye(n-k)]. +## +## @seealso{cyclgen, hammgen} +## @end deftypefn + +function par = gen2par (gen) + + if (nargin != 1) + print_usage (); + endif + + [gr, gc] = size (gen); + + if (gr > gc) + error ("gen2par: GEN must be a generator matrix in standard form"); + endif + + ## Identify where is the identity matrix + if (isequal (gen(:,1:gr), eye (gr))) + par = [gen(:,gr+1:gc)', eye(gc-gr)]; + elseif (isequal (gen(:,gc-gr+1:gc), eye (gr))) + par = [eye(gc-gr), gen(:,1:gc-gr)']; + else + error ("gen2par: GEN must be a generator matrix in standard form"); + endif + +endfunction + +%% Test input validation +%!error gen2par () +%!error gen2par (1, 2) +%!error gen2par ([1; 2]) diff --git a/inst/genqammod.m b/inst/genqammod.m new file mode 100644 index 0000000..9b70b8b --- /dev/null +++ b/inst/genqammod.m @@ -0,0 +1,59 @@ +## Copyright (C) 2006 Charalampos C. Tsimenidis +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{y} =} genqammod (@var{x}, @var{c}) +## +## Modulates an information sequence of integers @var{x} in the range +## @code{[0 @dots{} M-1]} onto a quadrature amplitude modulated signal +## @var{y}, where @code{M = length (c) - 1} and @var{c} is a 1D vector +## specifying the signal constellation mapping to be used. An example of +## combined 4PAM-4PSK is +## +## @example +## @group +## d = randint (1, 1e4, 8); +## c = [1+j -1+j -1-j 1-j 1+sqrt(3) j*(1+sqrt(3)) -1-sqrt(3) -j*(1+sqrt(3))]; +## y = genqammod (d, c); +## z = awgn (y, 20); +## plot (z, "rx") +## @end group +## @end example +## @seealso{genqamdemod} +## @end deftypefn + +function y = genqammod (x, c) + + if (nargin != 2) + print_usage (); + endif + + m = 0:length (c)-1; + if (!isempty (find (ismember (x, m) == 0))) + error ("genqammod: all elements of X must be integers in the range [0,M]"); + endif + + y = c(x+1); + +endfunction + +%!assert (genqammod ([0:7], [-7:2:7]), [-7:2:7]) +%!assert (genqammod ([0:7], [-7 -5 -1 -3 7 5 1 3]), [-7 -5 -1 -3 7 5 1 3]) + +%% Test input validation +%!error genqammod () +%!error genqammod (1) +%!error genqammod (1, 2, 3) +%!error genqammod (10, -7:2:7) diff --git a/inst/gftable.m b/inst/gftable.m new file mode 100644 index 0000000..7caf53c --- /dev/null +++ b/inst/gftable.m @@ -0,0 +1,31 @@ +## Copyright (C) 2002 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} gftable (@var{m}, @var{primpoly}) +## +## This function exists for compatibility with matlab. As the Octave Galois +## fields store a copy of the lookup tables for every field in use internally, +## there is no need to use this function. +## +## @seealso{gf} +## @end deftypefn + +function r = gftable (m, prim) + +endfunction + +%% Mark file as being tested. No test needed for function that does nothing. +%!assert (1) diff --git a/inst/gfweight.m b/inst/gfweight.m new file mode 100644 index 0000000..3a36de5 --- /dev/null +++ b/inst/gfweight.m @@ -0,0 +1,83 @@ +## Copyright (C) 2003 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{w} =} gfweight (@var{gen}) +## @deftypefnx {Function File} {@var{w} =} gfweight (@var{gen}, "gen") +## @deftypefnx {Function File} {@var{w} =} gfweight (@var{par}, "par") +## @deftypefnx {Function File} {@var{w} =} gfweight (@var{p}, n) +## +## Calculate the minimum weight or distance of a linear block code. The +## code can be either defined by its generator or parity check matrix, or +## its generator polynomial. By default if the first argument is a matrix, +## it is assumed to be the generator matrix of the code. The type of the +## matrix can be defined by a flag "gen" for the generator matrix or +## "par" for the parity check matrix. +## +## If the first argument is a vector, it is assumed that it defines the +## generator polynomial of the code. In this case a second argument is +## required that defines the codeword length. +## +## @seealso{hammgen, cyclpoly, bchpoly} +## @end deftypefn + +function w = gfweight (arg1, arg2) + + if (nargin < 1 || nargin > 2) + print_usage (); + endif + + if (isvector (arg1)) + if (nargin != 2) + error ("gfweight: codeword length required if first argument is a generator polynomial"); + endif + [ign, gen] = cyclgen (arg2, arg1); + elseif (ismatrix (arg1)) + if (nargin == 2) + if (ischar (arg2)) + if (strcmp (arg2, "gen")) + gen = arg1; + elseif (strcmp (arg2, "par")) + gen = gen2par (arg1); + else + error ("gfweight: invalid option '%s'", arg2); + endif + else + error ("gfweight: second argument must be a string if first argument is a matrix"); + endif + else + gen = arg1; + endif + else + error ("gfweight: first argument must be a matrix or a vector"); + endif + + [k, n] = size (gen); + if (n < k) + error ("gfweight: GEN must be a generator matrix in standard form"); + endif + + ## We only need to test codewords 1:2^k-1 against the zero code word + ## We do the equivalent of + ## w = min (sum ((mod (de2bi ([1:2^k-1]') * gen, 2))')); + ## But in a more memory efficient manner in an oct-file + w = __gfweight__ (gen); + +endfunction + +%% Test input validation +%!error gfweight () +%!error gfweight (1, 2, 3) +%!error gfweight ([1 2 3]) diff --git a/inst/golombdeco.m b/inst/golombdeco.m new file mode 100644 index 0000000..4f1dac6 --- /dev/null +++ b/inst/golombdeco.m @@ -0,0 +1,99 @@ +## Copyright (C) 2006 Muthiah Annamalai +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} golombdeco (@var{code}, @var{m}) +## +## Returns the Golomb decoded signal vector using @var{code} and @var{m}. +## Compulsory m is need to be specified. A restrictions is that a +## signal set must strictly be non-negative. The value of code +## is a cell array of row-vectors which have the encoded Golomb value +## for a single sample. The Golomb algorithm is +## used to encode the "code" and only that can be meaningfully +## decoded. @var{code} is assumed to have been of format generated +## by the function @code{golombenco}. Also the parameter @var{m} need to +## be a non-zero number, unless which it makes divide-by-zero errors. +## This function works backward the Golomb algorithm see +## @code{golombenco} for more details on that. +## Reference: Solomon Golomb, Run length Encodings, 1966 IEEE Trans Info Theory +## +## An example of the use of @code{golombdeco} is +## @example +## @group +## golombdeco (golombenco (1:4, 2), 2) +## @result{} [1 2 3 4] +## @end group +## @end example +## @seealso{golombenco} +## @end deftypefn + +##! /usr/bin/octave -q +#A stress test routine +#for i=1:100 +# sig=abs(randint(1,10,[0,255])); +# k=mod(i,10)+1; +# code=golombenco(sig,k); +# assert(golombdeco(code,k),sig) +#endfor +# +#for k=1:10; +# assert(golombdeco(golombenco(4:10,k),k),[4:10]); +#endfor +# + +function sig_op = golombdeco (code, m) + + if (nargin != 2 || ! iscell (code) || m <= 0) + print_usage (); + endif + + L = length (code); + C = ceil (log2 (m)); + partition_limit = 2**C - m; + + + power_seq = [2.^(ceil (log2 (m)) - 1:-1:0)]; + power_seq_mod = power_seq(2:end); + + for j = 1:L + word = code{j}; + WL = length (word); + idx = find (word == 0)(1); + q = sum (word(1:idx)); + + idx2 = (WL-idx); + word_tail = word(idx+1:end); + + if (length (word_tail) == C) + r = sum (word_tail.*power_seq); + r = r- (partition_limit); + else + r = sum (word_tail.*power_seq_mod); + endif + + quot(j) = q; + rem(j) = r; + endfor + sig_op = quot.*m + rem; + +endfunction + +%!assert (golombdeco (golombenco (1:4, 2), 2), [1:4]) + +%% Test input validation +%!error golombdeco () +%!error golombdeco (1) +%!error golombdeco (1, 2) +%!error golombdeco ({}, 0) diff --git a/inst/golombenco.m b/inst/golombenco.m new file mode 100644 index 0000000..1d6f5de --- /dev/null +++ b/inst/golombenco.m @@ -0,0 +1,112 @@ +## Copyright (C) 2006 Muthiah Annamalai +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} golombenco (@var{sig}, @var{m}) +## +## Returns the Golomb coded signal as cell array. +## Also total length of output code in bits can be obtained. +## This function uses a @var{m} need to be supplied for encoding signal vector +## into a Golomb coded vector. A restrictions is that +## a signal set must strictly be non-negative. Also the parameter @var{m} need to +## be a non-zero number, unless which it makes divide-by-zero errors. +## The Golomb algorithm [1], is used to encode the data into unary coded +## quotient part which is represented as a set of 1's separated from +## the K-part (binary) using a zero. This scheme doesn't need any +## kind of dictionaries, it is a parameterized prefix codes. +## Implementation is close to O(N^2), but this implementation +## *may be* sluggish, though correct. Details of the scheme are, to +## encode the remainder(r of number N) using the floor(log2(m)) bits +## when rem is in range 0:(2^ceil(log2(m)) - N), and encode it as +## r+(2^ceil(log2(m)) - N), using total of 2^ceil(log2(m)) bits +## in other instance it doesn't belong to case 1. Quotient is coded +## simply just using the unary code. Also according to [2] Golomb codes +## are optimal for sequences using the Bernoulli probability model: +## P(n)=p^n-1.q & p+q=1, and when M=[1/log2(p)], or P=2^(1/M). +## +## Reference: 1. Solomon Golomb, Run length Encodings, 1966 IEEE Trans +## Info' Theory. 2. Khalid Sayood, Data Compression, 3rd Edition +## +## An example of the use of @code{golombenco} is +## @example +## @group +## golombenco (1:4, 2) +## @result{} @{[0 1], [1 0 0], [1 0 1], [1 1 0 0]@} +## golombenco (1:10, 2) +## @result{} @{[0 1], [1 0 0], [1 0 1], [1 1 0 0], +## [1 1 0 1], [1 1 1 0 0], [1 1 1 0 1], [1 1 1 1 0 0], +## [1 1 1 1 0 1], [1 1 1 1 1 0 0]@} +## @end group +## @end example +## @seealso{golombdeco} +## @end deftypefn + +function [gcode, Ltot] = golombenco (sig, m) + + if (nargin != 2 || m <= 0) + print_usage (); + endif + + if (min (sig) < 0) + error ("golombenco: all elements of SIG must be non-negative numbers"); + endif + + L = length (sig); + quot = floor (sig./m); + rem = sig-quot.*m; + + + C = ceil (log2 (m)); + partition_limit = 2**C-m; + Ltot = 0; + for j = 1:L + if ( rem(j) < partition_limit ) + BITS = C-1; + else + rem(j) = rem(j)+partition_limit; + BITS = C; + endif + Ltot = Ltot+BITS+1; + golomb_part = zeros (1, BITS); + + ## + ## How can we eliminate this loop? + ## I essentially need to get the binary + ## representation of rem(j) in the golomb_part(i); + ## -maybe when JWE or someone imports dec2binvec. + ## This does MSB -> LSB + for i = BITS:-1:1 + golomb_part(i) = mod (rem(j), 2); + rem(j) = floor (rem(j)/2); + endfor + + ## + ## actual golomb code: sandwich the unary coded quotient, + ## and the remainder. + ## + gcode{j} = [ones(1, quot(j)) 0 golomb_part]; + endfor + Ltot = sum (quot)+Ltot; + +endfunction + +%!assert (golombenco (3:5, 5), {[0 1 1 0], [0 1 1 1], [1 0 0 0 ]}) +%!assert (golombenco (3:5, 3), {[1 0 0] , [1 0 1 0], [1 0 1 1]}) + +%% Test input validation +%!error golombenco () +%!error golombenco (1) +%!error golombenco (1, 2, 3) +%!error golombenco (1, 0) diff --git a/inst/hammgen.m b/inst/hammgen.m new file mode 100644 index 0000000..69c18b8 --- /dev/null +++ b/inst/hammgen.m @@ -0,0 +1,80 @@ +## Copyright (C) 2003 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{h} =} hammgen (@var{m}) +## @deftypefnx {Function File} {@var{h} =} hammgen (@var{m}, @var{p}) +## @deftypefnx {Function File} {[@var{h}, @var{g}] =} hammgen (@dots{}) +## @deftypefnx {Function File} {[@var{h}, @var{g}, @var{n}, @var{k}] =} hammgen (@dots{}) +## +## Produce the parity check and generator matrices of a Hamming code. The +## variable @var{m} defines the [@var{n},@var{k}] Hamming code where +## @code{@var{n} = 2 ^ @var{m} - 1} and @code{@var{k} = @var{n} - @var{m}}. +## @var{m} must be between 3 and 16. +## +## The parity check matrix is generated relative to the primitive polynomial +## of GF(2^@var{m}). If @var{p} is specified the default primitive polynomial +## of GF(2^@var{m}) is overridden. @var{p} must be a valid primitive +## polynomial of the correct order for GF(2^@var{m}). +## +## The parity check matrix is returned in the @var{m} by @var{n} matrix +## @var{h}, and if requested the generator matrix is returned in the @var{k} +## by @var{n} matrix @var{g}. +## +## @seealso{gen2par} +## @end deftypefn + +function [h, g, n, k] = hammgen (m, p) + + if (nargin < 1 || nargin > 2) + print_usage (); + endif + + if (! (isscalar (m) && m == fix (m) && m >= 3 && m <= 16)) + error ("hammgen: M must be an integer in the range [3,16]"); + endif + + if (nargin > 1) + if (!isscalar (p)) + p = bi2de (p); + endif + if (! (p == fix (p) && p >= 2^m && p <= 2^(m+1) && isprimitive (p))) + error ("hammgen: P must be a primitive polynomial of GF(2^M)"); + endif + else + ## Get the primitive polynomial of GF(2^M). Note that the default + ## primitive polynomial is not necessarily primpoly(m,"min"), so + ## have to create a Galois variable to extract the default primitive. + ## The problem is, this limits m to be less than or equal to 16, + ## as the Galois type itself is limited to this value + p = gf (0, m).prim_poly; + endif + + n = 2^m -1; + k = n - m; + if (nargout > 1) + [h, g] = cyclgen (n, p); + else + h = cyclgen (n, p); + endif + +endfunction + +%% Test input validation +%!error hammgen () +%!error hammgen (1, 2, 3) +%!error hammgen (1) +%!error hammgen (20) +%!error hammgen (3, 4) diff --git a/inst/helintrlv.m b/inst/helintrlv.m new file mode 100644 index 0000000..51da3ba --- /dev/null +++ b/inst/helintrlv.m @@ -0,0 +1,80 @@ +## Copyright (C) 2010 Mark Borgerding +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{outdata} =} helintrlv (@var{data}, @var{col}, @var{ngrp}, @var{stp}) +## @var{col}-by-@var{ngrp}. +## @seealso{heldeintrlv} +## @end deftypefn + +function [outdata, outstate] = helintrlv (data, col, ngrp, stp, init_state) + + if (nargin < 4 || nargin > 5) + print_usage (); + endif + + if (! (isscalar (col) && col == fix (col))) + error ("helintrlv: COL must be an integer"); + endif + + if (! (isscalar (ngrp) && ngrp == fix (ngrp))) + error ("helintrlv: NGRP must be an integer"); + endif + + didTranspose = 0; + if (isvector (data) && columns (data) > rows (data)) + data = data.'; + didTranspose = 1; + endif + + s = size (data); + + if (s(1) != col*ngrp) + error ("helintrlv: DATA must have length equal to COL*NGRP"); + endif + + if (nargin == 4) + init_state = zeros (stp*col*(col-1)/2, s(2)); + endif + + outstate = []; + # for each column + for k = 1:s(2) + tmp = reshape (data(:,k), ngrp, col); + instate = init_state(:,k); + outstateCol = []; + for k1 = 2:col + curStepSize = (k1-1)*stp; + tmpCol = [instate(1:curStepSize); tmp(:,k1)]; + tmp(:,k1) = tmpCol(1:ngrp); + outstateCol = [outstateCol; tmpCol(end+1-curStepSize:end)]; + instate = instate(curStepSize+1:end); + endfor + outdata(:,k) = reshape (tmp.', s(1), 1); + outstate = [outstate outstateCol]; + endfor + + if (didTranspose) + outdata = outdata.'; + endif + +endfunction + +%% Test input validation +%!error helintrlv () +%!error helintrlv (1) +%!error helintrlv (1, 2) +%!error helintrlv (1, 2, 3) +%!error helintrlv (1, 2, 3, 4, 5, 6) diff --git a/inst/helscandeintrlv.m b/inst/helscandeintrlv.m new file mode 100644 index 0000000..29dda1e --- /dev/null +++ b/inst/helscandeintrlv.m @@ -0,0 +1,26 @@ +## Copyright (C) 2010 Mark Borgerding +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{outdata} =} helscandeintrlv (@var{data}, @var{nrows}, @var{ncols}, @var{Nshift}) +## @var{nrows}-by-@var{ncols}. +## @seealso{helscandeintrlv} +## @end deftypefn + +function outdata = helscandeintrlv (data, Nrows, Ncols, Nshift) + + outdata = helscanintrlv (data, Nrows, Ncols, Nrows - Nshift); + +endfunction diff --git a/inst/helscanintrlv.m b/inst/helscanintrlv.m new file mode 100644 index 0000000..2703d07 --- /dev/null +++ b/inst/helscanintrlv.m @@ -0,0 +1,70 @@ +## Copyright (C) 2010 Mark Borgerding +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{outdata} =} helscanintrlv (@var{data}, @var{nrows}, @var{ncols}, @var{Nshift}) +## @var{nrows}-by-@var{ncols}. +## @seealso{helscandeintrlv} +## @end deftypefn + +function outdata = helscanintrlv (data, Nrows, Ncols, Nshift) + + if (nargin != 4) + print_usage (); + endif + + if (! (isscalar (Nrows) && Nrows == fix (Nrows))) + error ("helscanintrlv: NROWS must be an integer"); + endif + + if (! (isscalar (Ncols) && Ncols == fix (Ncols))) + error ("helscanintrlv: NCOLS must be an integer"); + endif + + didTranspose = 0; + if (isvector (data) && columns (data) > rows (data)) + data = data.'; + didTranspose = 1; + endif + + s = size (data); + + if (size (data, 1) != Nrows*Ncols) + error ("helscanintrlv: DATA must have length equal to NCOLS*NROWS"); + endif + + # create the interleaving indices + idx0 = 0:Nrows*Ncols-1; + idxMod = rem (idx0, Ncols); + idxFlr = idx0 - idxMod; + inds = 1 + rem (idxFlr + idxMod * Ncols * Nshift + idxMod, Nrows*Ncols); + + # for each column + for k = 1:s(2) + outdata(:,k) = data(inds,k); + endfor + + if (didTranspose) + outdata = outdata.'; + endif + +endfunction + +%% Test input validation +%!error helscanintrlv () +%!error helscanintrlv (1) +%!error helscanintrlv (1, 2) +%!error helscanintrlv (1, 2, 3) +%!error helscanintrlv (1, 2, 3, 4, 5) diff --git a/inst/huffmandeco.m b/inst/huffmandeco.m new file mode 100644 index 0000000..072b21c --- /dev/null +++ b/inst/huffmandeco.m @@ -0,0 +1,112 @@ +## Copyright (C) 2006 Muthiah Annamalai +## Copyright (C) 2011 Ferran Mesas Garcia +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{sig} =} huffmandeco (@var{hcode}, @var{dict}) +## Decode signal encoded by @code{huffmanenco}. +## +## This function uses a dict built from the +## @code{huffmandict} and uses it to decode a signal list into a Huffman +## list. A restriction is that @var{hcode} is expected to be a binary code +## +## The returned @var{sig} set that strictly belongs in the range @code{[1,N]} +## with @code{N = length (@var{dict})}. Also @var{dict} can only be from the +## @code{huffmandict} routine. Whenever decoding fails, those signal values a +## re indicated by @code{-1}, and we successively try to restart decoding +## from the next bit that hasn't failed in decoding, ad-infinitum. An example +## of the use of @code{huffmandeco} is: +## +## @example +## @group +## hd = huffmandict (1:4, [0.5 0.25 0.15 0.10]); +## hcode = huffmanenco (1:4, hd); +## back = huffmandeco (hcode, hd) +## @result{} [1 2 3 4] +## @end group +## @end example +## @seealso{huffmandict, huffmanenco} +## @end deftypefn + +function symbols = huffmandeco (hcode, dict) + + if (nargin != 2) + print_usage (); + elseif (!all ((hcode == 1) + (hcode == 0)) || !isvector (hcode)) + error ("huffmandeco: HCODE must be a binary vector"); + elseif (! iscell (dict)) + error ("huffmandeco: DICT must be a dictionary from huffmandict"); + endif + + ## Convert the Huffman Dictionary to a Huffman Tree represented by + ## an array. + tree = dict2tree (dict); + + ## Traverse the tree and store the symbols. + symbols = []; + pointer = 1; # a pointer to a node of the tree. + for i = 1:length (hcode); + if (tree(pointer) != -1) + symbols = [symbols, tree(pointer)]; + pointer = 1; + endif + pointer = 2 * pointer + hcode(i); + endfor + + ## Check if decodification was successful + if (tree(pointer) == -1) + warning ("huffmandeco: could not decode last symbol") + endif + symbols = [symbols, tree(pointer)]; + +endfunction + +function tree = dict2tree (dict) + + L = length (dict); + lengths = zeros (1, L); + + ## the depth of the tree is limited by the maximum word length. + for i = 1:L + lengths(i) = length (dict{i}); + endfor + m = max (lengths); + + tree = zeros (1, 2^(m+1)-1)-1; + + for i = 1:L + pointer = 1; + word = dict{i}; + for bit = word + pointer = 2 * pointer + bit; + endfor + tree(pointer) = i; + endfor + +endfunction + +%!assert (huffmandeco (huffmanenco (1:4, huffmandict (1:4, [0.5 0.25 0.15 0.10])), huffmandict (1:4, [0.5 0.25 0.15 0.10])), [1:4], 0) +%!assert (huffmandeco (huffmanenco ([1:100 100:-1:1], huffmandict (1:100, ones (1, 100)/100)), huffmandict (1:100, ones (1, 100)/100)), [1:100 100:-1:1], 0) +%!assert (huffmandeco ([huffmanenco(1:4, huffmandict (1:4, [0.5 0.25 0.15 0.10])) 0], huffmandict (1:4, [0.5 0.25 0.15 0.10])), [1:4 -1], 0) +%!fail ("huffmandeco ([huffmanenco(1:4, huffmandict (1:4, [0.5 0.25 0.15 0.10])) 0], huffmandict (1:4, [0.5 0.25 0.15 0.10]))", "warning") +%!fail ("huffmandeco ('this is not a code', huffmandict (1:4, [0.5 0.25 0.15 0.10]))") +%!fail ("huffmandeco ([1 0 1 0], 'this is not a dictionary')") + +%% Test input validation +%!error huffmandeco () +%!error huffmandeco (1) +%!error huffmandeco (1, 2, 3) +%!error huffmandeco (1, 2) +%!error huffmandeco (2, {}) diff --git a/inst/huffmandict.m b/inst/huffmandict.m new file mode 100644 index 0000000..6a02d49 --- /dev/null +++ b/inst/huffmandict.m @@ -0,0 +1,219 @@ +## Copyright (C) 2006 Muthiah Annamalai +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} huffmandict (@var{symb}, @var{prob}) +## @deftypefnx {Function File} {} huffmandict (@var{symb}, @var{prob}, @var{toggle}) +## @deftypefnx {Function File} {} huffmandict (@var{symb}, @var{prob}, @var{toggle}, @var{minvar}) +## +## Builds a Huffman code, given a probability list. The Huffman codes +## per symbol are output as a list of strings-per-source symbol. A zero +## probability symbol is NOT assigned any codeword as this symbol doesn't +## occur in practice anyway. +## +## @var{toggle} is an optional argument with values 1 or 0, that starts +## building a code based on 1s or 0s, defaulting to 0. Also @var{minvar} +## is a boolean value that is useful in choosing if you want to optimize +## buffer for transmission in the applications of Huffman coding, however +## it doesn't affect the type or average codeword length of the generated +## code. An example of the use of @code{huffmandict} is +## +## @example +## @group +## huffmandict (symbols, [0.5 0.25 0.15 0.1], 1) +## @result{} @{[0], [1 0], [1 1 1], [1 1 0]@} +## huffmandict (symbols, 0.25 * ones (1,4), 1) +## @result{} @{[1 1], [1 0], [0 1], [0 0]@} +## +## prob = [0.5 0 0.25 0.15 0.1]; +## dict = huffmandict (1:5, prob, 1); +## entropy (prob) +## @result{} 2.3219 +## laverage (dict, prob) +## @result{} 1.8500 +## +## x = [0.2 0.4 0.2 0.1 0.1]; +## huffmandict (1, x, 0, true) +## @result{} @{[1 0], [0 0], [1 1], [0 1 0], [0 1 1]@} +## huffmandict (1, x) +## @result{} @{[0 1], [1], [0 0 1], [0 0 0 0], [0 0 0 1]@} +## @end group +## @end example +## +## Reference: Dr.Rao's course EE5351 Digital Video Coding, at UT-Arlington. +## @seealso{huffmandeco, huffmanenco} +## @end deftypefn + +## Huffman code algorithm. +## while (uncombined_symbols_remain) +## combine least probable symbols into one with, +## their probability being the sum of the two. +## save this result as a stage at lowest order rung. +## (Moving to lowest position possible makes it non-minimum variance +## entropy coding) +## end +## +## for each (stage) +## Walk the tree we built, and assign each row either 1, +## or 0 of +## end +## +## reverse each symbol, and dump it out. +## + +function cw_list = huffmandict (sym, source_prob, togglecode = 0, minvar = 0) + + if (nargin < 2) + print_usage (); + ## need to compare to 1 + elseif ((sum (source_prob) - 1.0) > 1e-7) + error ("huffmandict: the elements of PROB must add up to 1"); + endif + + ## need to find & eliminate the zero-probability code words. + ## in practice we donot need to assign anything to them. Reasoning + ## being that if_ it doesnt occur why bother saving its value anyway? + ## --(Oct 9) Actually some experts in the area dont agree to this, + ## and being a generic implementation we should stick to generating + ## CWs for_ zero symbols. Why impose a bad implementation? --Muthu + + origsource_prob = source_prob; + + ## sort the list and know the index transpositions. kills the speed O(n^2). + L = length (source_prob); + index = [1:L]; + for itr1 = 1:L + for itr2 = itr1:L + if (source_prob(itr1) < source_prob(itr2)) + t = source_prob(itr1); + source_prob(itr1) = source_prob(itr2); + source_prob(itr2) = t; + + t = index(itr1); + index(itr1) = index(itr2); + index(itr2) = t; + endif + endfor + endfor + + stage_list = {}; + cw_list = cell (1, L); + + stage_curr = {}; + stage_curr.prob_list = source_prob; + stage_curr.sym_list = {}; + S = length (source_prob); + for i = 1:S; + stage_curr.sym_list{i} = [i]; + #cw_list{i} = ""; + endfor + + ## another O(n^2) part. + I = 1; + while (I < S) + L = length (stage_curr.prob_list); + nprob = stage_curr.prob_list(L-1) + stage_curr.prob_list(L); + nsym = [stage_curr.sym_list{L-1}(1:end), stage_curr.sym_list{L}(1:end)]; + + ## stage_curr; + ## archive old stage list. + stage_list{I} = stage_curr; + + ## insert the new probability into the list, at the + ## first-position (greedy?) possible. + for i = 1:(L-2) + if ((minvar && stage_curr.prob_list(i) <= nprob) || ... + stage_curr.prob_list(i) < nprob) + break; + endif + endfor + + + + stage_curr.prob_list = [stage_curr.prob_list(1:i-1) nprob stage_curr.prob_list(i:L-2)]; + stage_curr.sym_list = {stage_curr.sym_list{1:i-1}, nsym, stage_curr.sym_list{i:L-2}}; + + ## Loopie + I = I + 1; + endwhile + + if (togglecode == 0) + one_cw = 1; + zero_cw = 0; + else + one_cw = 0; + zero_cw = 1; + endif + + ## another O(n^2) part. + I = I - 1; + while (I > 0) + stage_curr = stage_list{I}; + L = length (stage_curr.sym_list); + + clist = stage_curr.sym_list{L}; + for k = 1:length (clist) + cw_list{1,clist(k)} = [cw_list{1,clist(k)} one_cw]; + endfor + + clist = stage_curr.sym_list{L-1}; + for k = 1:length (clist) + cw_list{1,clist(k)} = [cw_list{1,clist(k)}, zero_cw]; + endfor + + ## Loopie + I = I - 1; + endwhile + + ## zero all the code-words of zero-probability length, 'cos they + ## never occur. + S = length (source_prob); + for itr = (S+1):length (origsource_prob) + cw_list{1,itr} = -1; + endfor + + #disp("Before resorting") + #cw_list + + nw_list = cell (1, L); + ## + ## Re-sort the indices according to the probability list. + ## + L = length (source_prob); + for itr = 1:(L) + t = cw_list{index(itr)}; + nw_list{index(itr)} = cw_list{itr}; + endfor + cw_list = nw_list; + + ## zero all the code-words of zero-probability length, 'cos they + ## never occur. + + #for itr = 1:L + # if (origsource_prob(itr) == 0) + # cw_list{itr} = ""; + # endif + #endfor + +endfunction + +%!assert (huffmandict (1:4, [0.5 0.25 0.15 0.1], 1), {[0], [1 0], [1 1 1], [1 1 0]}, 0) +%!assert (huffmandict (1:4, 0.25*ones (1, 4), 1), {[1 1], [1 0], [0 1], [0 0]}, 0) +%!assert (huffmandict (1:4, [1 0 0 0 ]), {[1], [0 1], [0 0 0], [0 0 1]}, 0) + +%% Test input validation +%!error huffmandict () +%!error huffmandict (1) +%!error huffmandict (1, [0.5 0.5 0.5]) diff --git a/inst/huffmanenco.m b/inst/huffmanenco.m new file mode 100644 index 0000000..ee35391 --- /dev/null +++ b/inst/huffmanenco.m @@ -0,0 +1,54 @@ +## Copyright (C) 2006 Muthiah Annamalai +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} huffmanenco (@var{sig}, @var{dict}) +## +## Returns the Huffman encoded signal using @var{dict}. This function uses +## a @var{dict} built from the @code{huffmandict} and uses it to encode a +## signal list into a Huffman list. A restrictions is that a signal set must +## strictly belong in the range @code{[1,N]} with @code{N = length (dict)}. +## Also @var{dict} can only be from the @code{huffmandict} routine. +## An example of the use of @code{huffmanenco} is +## +## @example +## @group +## hd = huffmandict (1:4, [0.5 0.25 0.15 0.10]); +## huffmanenco (1:4, hd) +## @result{} [1 0 1 0 0 0 0 0 1] +## @end group +## @end example +## @seealso{huffmandict, huffmandeco} +## @end deftypefn + +function hcode = huffmanenco (sig, dict) + + if (nargin != 2 || ! iscell (dict)) + print_usage (); + elseif (max (sig) > length (dict) || min (sig) < 1) + error ("huffmanenco: all elements of SIG must be integers in the range [1,N]"); + endif + hcode = [dict{sig}]; + +endfunction + +%!assert (huffmanenco (1:4, huffmandict (1:4, [0.5 0.25 0.15 0.10])), [1 0 1 0 0 0 0 0 1], 0) + +%% Test input validation +%!error huffmanenco () +%!error huffmanenco (1) +%!error huffmanenco (1, 2) +%!error huffmanenco (1, 2, 3) +%!error huffmanenco (1, {}) diff --git a/inst/intrlv.m b/inst/intrlv.m new file mode 100644 index 0000000..e5b027f --- /dev/null +++ b/inst/intrlv.m @@ -0,0 +1,49 @@ +## Copyright (C) 2008 Sylvain Pelissier +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{intrlvd} =} intrlv (@var{data}, @var{elements}) +## Interleaved elements of @var{data} according to @var{elements}. +## @seealso{deintrlv} +## @end deftypefn + +function intrlvd = intrlv (data, elements) + + if (nargin != 2) + print_usage (); + endif + + if (!isvector (elements)) + error ("intrlv: ELEMENTS must be a vector"); + endif + + if (isvector (data)) + if (length (elements) != length (data) || any (sort (elements) != 1:length (data))) + error ("intrlv: ELEMENTS must be a permutation of DATA indices"); + endif + intrlvd = data(elements); + else + if (length (elements) != size (data, 1) || any (sort (elements) != 1:size (data, 1))) + error ("intrlv: ELEMENTS must be a permutation of DATA indices"); + endif + intrlvd = data(elements,:); + endif + +endfunction + +%% Test input validation +%!error intrlv () +%!error intrlv (1) +%!error intrlv (1, 2, 3) diff --git a/inst/istrellis.m b/inst/istrellis.m new file mode 100644 index 0000000..4eac5b7 --- /dev/null +++ b/inst/istrellis.m @@ -0,0 +1,110 @@ +## Copyright (C) 2012 Mike Miller +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} istrellis (@var{t}) +## @deftypefnx {Function File} {[@var{status}, @var{text}] =} istrellis (@var{t}) +## +## Return true if @var{t} is a valid trellis structure. +## +## If called with two output arguments, @var{text} contains a string indicating +## a reason if @var{status} is false or an empty string if @var{status} is true. +## +## @seealso{poly2trellis, struct} +## @end deftypefn + +function [status, text] = istrellis (t) + + if (nargin != 1) + print_usage (); + endif + + status = false; + text = ""; + + if (! (isstruct (t) + && isfield (t, "numInputSymbols") + && isfield (t, "numOutputSymbols") + && isfield (t, "numStates") + && isfield (t, "nextStates") + && isfield (t, "outputs"))) + text = "t is not a valid trellis structure"; + else + try + outputs = oct2dec (t.outputs); + outputs_is_octal = true; + catch + outputs_is_octal = false; + end_try_catch + k = log2 (t.numInputSymbols); + n = log2 (t.numOutputSymbols); + nu = log2 (t.numStates); + if (! (isscalar (k) && k == fix (k) && k >= 0)) + text = "numInputSymbols is not a power of 2"; + elseif (! (isscalar (n) && n == fix (n) && n >= 0)) + text = "numOutputSymbols is not a power of 2"; + elseif (! (isscalar (nu) && nu == fix (nu) && nu >= 0)) + text = "numStates is not a power of 2"; + elseif (any (size (t.nextStates) != [t.numStates t.numInputSymbols])) + text = "nextStates is not a numStates-by-numInputSymbols matrix"; + elseif (any (size (t.outputs) != [t.numStates t.numInputSymbols])) + text = "outputs is not a numStates-by-numInputSymbols matrix"; + elseif (! (all (t.nextStates(:) == fix (t.nextStates(:))) + && all (t.nextStates(:) >= 0) + && all (t.nextStates(:) < t.numStates))) + text = "nextStates must contain integers from 0 to numStates-1"; + elseif (! (outputs_is_octal + && all (t.outputs(:) == fix (t.outputs(:))) + && all (t.outputs(:) >= 0) + && all (outputs(:) < t.numOutputSymbols))) + text = "outputs must contain octal integers from 0 to numOutputSymbols-1"; + else + status = true; + endif + endif + +endfunction + +%% Test the simple (2,1,3) encoder from Lin & Costello example 11.1 +%!test +%! T = struct ("numInputSymbols", 2, +%! "numOutputSymbols", 4, +%! "numStates", 8, +%! "nextStates", [0 4; 0 4; 1 5; 1 5; 2 6; 2 6; 3 7; 3 7], +%! "outputs", [0 3; 3 0; 3 0; 0 3; 1 2; 2 1; 2 1; 1 2]); +%! assert (istrellis (T), true) + +%% Tests of invalid arguments or invalid structures +%!test +%! [status, text] = istrellis ([]); +%! assert (status, false); +%! assert (isempty (strfind (text, "not a valid trellis")), false) +%!test +%! [status, text] = istrellis (struct ()); +%! assert (status, false); +%! assert (isempty (strfind (text, "not a valid trellis")), false) +%!test +%! T = struct ("numInputSymbols", 3, +%! "numOutputSymbols", 4, +%! "numStates", 0, +%! "nextStates", zeros (0, 4), +%! "outputs", zeros (0, 4)); +%! [status, text] = istrellis (T); +%! assert (status, false); +%! assert (isempty (strfind (text, "numInputSymbols")), false) + +%% Test input validation +%!error istrellis () +%!error istrellis (1, 2) diff --git a/inst/lloyds.m b/inst/lloyds.m new file mode 100644 index 0000000..e88eb9b --- /dev/null +++ b/inst/lloyds.m @@ -0,0 +1,177 @@ +## Copyright (C) 2003 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {[@var{table}, @var{codes}] =} lloyds (@var{sig}, @var{init_codes}) +## @deftypefnx {Function File} {[@var{table}, @var{codes}] =} lloyds (@var{sig}, @var{len}) +## @deftypefnx {Function File} {[@var{table}, @var{codes}] =} lloyds (@var{sig}, @dots{}, @var{tol}) +## @deftypefnx {Function File} {[@var{table}, @var{codes}] =} lloyds (@var{sig}, @dots{}, @var{tol}, @var{type}) +## @deftypefnx {Function File} {[@var{table}, @var{codes}, @var{dist}] =} lloyds (@dots{}) +## @deftypefnx {Function File} {[@var{table}, @var{codes}, @var{dist}, @var{reldist}] =} lloyds (@dots{}) +## +## Optimize the quantization table and codes to reduce distortion. This is +## based on the article by Lloyd +## +## S. Lloyd @emph{Least squared quantization in PCM}, IEEE Trans Inform +## Theory, Mar 1982, no 2, p129-137 +## +## which describes an iterative technique to reduce the quantization error +## by making the intervals of the table such that each interval has the same +## area under the PDF of the training signal @var{sig}. The initial codes to +## try can either be given in the vector @var{init_codes} or as scalar +## @var{len}. In the case of a scalar the initial codes will be an equi-spaced +## vector of length @var{len} between the minimum and maximum value of the +## training signal. +## +## The stopping criteria of the iterative algorithm is given by +## +## @example +## abs(@var{dist}(n) - @var{dist}(n-1)) < max(@var{tol}, abs(@var{eps}*max(@var{sig})) +## @end example +## +## By default @var{tol} is 1.e-7. The final input argument determines how the +## updated table is created. By default the centroid of the values of the +## training signal that fall within the interval described by @var{codes} +## are used to update @var{table}. If @var{type} is any other string than +## "centroid", this behavior is overridden and @var{table} is updated as +## follows. +## +## @example +## @var{table} = (@var{code}(2:length(@var{code})) + @var{code}(1:length(@var{code}-1))) / 2 +## @end example +## +## The optimized values are returned as @var{table} and @var{code}. In +## addition the distortion of the optimized codes representing the training +## signal is returned as @var{dist}. The relative distortion in the final +## iteration is also returned as @var{reldist}. +## +## @seealso{quantiz} +## @end deftypefn + +function [table, code, dist, reldist] = lloyds (sig, init, tol, type) + + if (nargin < 2 || nargin > 4) + print_usage (); + endif + + if (min (size (sig)) != 1) + error ("lloyds: SIG must be a vector"); + endif + + sig = sig(:); + sigmin = min (sig); + sigmax = max (sig); + + if (length (init) == 1) + len = init; + init = [0:len-1]' / (len - 1) * (sigmax - sigmin) + sigmin; + elseif (min (size (init))) + len = length (init); + else + error ("lloyds: invalid initial codebook"); + endif + lcode = length (init); + + if (any (init != sort (init))) + ## Must be monotonically increasing + error ("lloyds: INIT_CODES must be monotonically increasing"); + endif + + if (nargin < 3) + tol = 1e-7; + elseif (isempty (tol)) + tol = 1e-7; + endif + stop_criteria = max (eps * abs (sigmax), abs (tol)); + + if (nargin < 4) + type = "centroid"; + elseif (!ischar (type)) + error ("lloyds: TYPE must be a string"); + endif + + ## Setup initial codebook, table and distortion + code = init(:); + table = (code(2:lcode) + code(1:lcode-1))/2; + [indx, ignore, dist] = quantiz (sig, table, code); + reldist = abs (dist); + + while (reldist > stop_criteria) + ## The formula of the code at the new iteration is + ## + ## code = Int_{table_{i-1}}^{table_i} x PSD(sig(x)) dx / .. + ## Int_{table_{i-1}}^{table_i} PSD(sig(x)) dx + ## + ## As sig is a discrete signal, this comes down to counting the number + ## of times "sig" has values in each interval of the table, and taking + ## the mean of these values. If no value of the signals in interval, take + ## the middle of the interval. That is calculate the centroid of the data + ## of the training signal falling in the interval. We can reuse the index + ## from the previous call to quantiz to define the values in the interval. + for i = 1:lcode + psd_in_interval = find (indx == i-1); + if (!isempty (psd_in_interval)) + code(i) = mean (sig(psd_in_interval)); + elseif (i == 1) + code(i) = (table(i) + sigmin) / 2; + elseif (i == lcode) + code(i) = (sigmax + table(i-1)) / 2; + else + code(i) = (table(i) + table(i-1)) / 2; + endif + endfor + + ## Now update the table. There is a problem here, in that I believe + ## the elements of the new table should be given by b(i)=(c(i+1)+c(i))/2, + ## but Matlab doesn't seem to do this. Matlab seems to also take the + ## centroid of the code for the table (this was a real pain to find + ## why my results and Matlab's disagreed). For this reason, I have a + ## default behavior the same as Matlab, and allow a flag to overide + ## it to be the behavior I expect. If any one wants to tell me what + ## the CORRECT behavior is, then I'll get rid of of the irrelevant + ## case below. + if (strcmp (type, "centroid")) + for i = 1:lcode-1; + sig_in_code = sig(find (sig >= code(i))); + sig_in_code = sig_in_code(find (sig_in_code < code(i+1))); + if (!isempty (sig_in_code)) + table(i) = mean (sig_in_code); + else + table(i) = (code(i+1) + code(i)) / 2; + endif + endfor + else + table = (code(2:lcode) + code(1:lcode-1))/2; + endif + + ## Update the distortion levels + reldist = dist; + [indx, ignore, dist] = quantiz (sig, table, code); + reldist = abs (reldist - dist); + endwhile + + if (size (init, 1) == 1) + code = code'; + table = table'; + endif + +endfunction + +%% Test input validation +%!error lloyds () +%!error lloyds (1) +%!error lloyds (1, 2, 3, 4, 5) +%!error lloyds (1, [3 2 1]) +%!error lloyds (1, 2, 3, 4) diff --git a/inst/lz77deco.m b/inst/lz77deco.m new file mode 100644 index 0000000..89d3508 --- /dev/null +++ b/inst/lz77deco.m @@ -0,0 +1,82 @@ +## Copyright (C) 2007 Gorka Lertxundi +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{m} =} lz77deco (@var{c}, @var{alph}, @var{la}, @var{n}) +## Lempel-Ziv 77 source algorithm decoding implementation. Where +## +## @table @asis +## @item @var{m} +## message decoded (1xN). +## @item @var{c} +## encoded message (Mx3). +## @item @var{alph} +## size of alphabet. +## @item @var{la} +## lookahead buffer size. +## @item @var{n} +## sliding window buffer size. +## @end table +## @seealso{lz77enco} +## @end deftypefn + +function m = lz77deco (c, alph, la, n) + + if (la <= 0 || n <= 0) + error ("lz77deco: LA and N must be positive integers"); + endif + if (n - la < la) + error ("lz77deco: N must be >= 2*LA"); + endif + if (alph < 2) + error ("lz77deco: ALPH must be >= 2"); + endif + if (columns (c) != 3) + error ("lz77deco: C must be a matrix with 3 columns"); + endif + + window = zeros (1, n); + x = length (c); + len = length (c); + + for x = 1:len + ## update window + temp = n - la + c(x,2) - c(x,1); + for y = 1:temp + window(n-la+y) = window(c(x,1)+y); + endfor + window(n-la+c(x,2)+1) = c(x,3); + + ## decoded message + m_deco = window(n-la+1:n-la+c(x,2)+1); + if (x == 1) + m = m_deco; + else + m = [m m_deco]; + endif + + ## CCW shift + temp = c(x,2) + 1; + window(1:n-la) = window(temp+1:n-la+temp); + endfor + +endfunction + +%!demo +%! lz77deco ([8 2 1 ; 7 3 2 ; 6 7 2 ; 2 8 0], 3, 9, 18) + +%% Test input validation +%!error lz77deco (1, 2, 3, 4) +%!error lz77deco (1, 1, 1, 1) diff --git a/inst/lz77enco.m b/inst/lz77enco.m new file mode 100644 index 0000000..6fa0905 --- /dev/null +++ b/inst/lz77enco.m @@ -0,0 +1,97 @@ +## Copyright (C) 2007 Gorka Lertxundi +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{c} =} lz77enco (@var{m}, @var{alph}, @var{la}, @var{n}) +## Lempel-Ziv 77 source algorithm implementation. Where +## +## @table @asis +## @item @var{c} +## encoded message (Mx3). +## @item @var{alph} +## size of alphabet. +## @item @var{la} +## lookahead buffer size. +## @item @var{n} +## sliding window buffer size. +## @end table +## @seealso{lz77deco} +## @end deftypefn + +function c = lz77enco (m, alph, la, n) + + if (la <= 0 || n <= 0) + error ("lz77enco: LA and N must be positive integers"); + endif + if (n - la < la) + error ("lz77deco: N must be >= 2*LA"); + endif + if (alph < 2) + error ("lz77enco: ALPH must be >= 2"); + endif + if (max (m) + 1 > alph) + error ("lz77enco: ALPH must be greater than the largest element of M"); + endif + if (rows (m) != 1) + error ("lz77enco: M must be a row vector"); + endif + + c = zeros (1, 3); + enco = zeros (1, 3); + window = zeros (1, n); + x = length (m); + len = length (m); + + while (x != 0) + ## update window + window(1:n-la) = window(enco(2)+2:n-la+enco(2)+1); + if (x < la) + window(n-la+1:n) = [m(len-x+1:len) zeros(1, la-x)]; + else + window(n-la+1:n) = m(len-x+1:len-x+la); + endif + + ## get a reference (position,length) to longest match, and next symbol + enco = [0 0 0]; + for y = (n-la):-1:1 + z = 0; + while (z != la && window(y+z) == window(n-la+z+1)) + z += 1; + endwhile + + if (enco(2) < z) + enco(1) = y-1; + enco(2) = z; + enco(3) = window(n-la+z+1); + endif + endfor + + ## encoded message + if (x == len) + c = enco; + else + c = [c ; enco]; + endif + + x -= enco(2)+1; + endwhile + +endfunction + +%!demo +%! lz77enco ([0 0 1 0 1 0 2 1 0 2 1 0 2 1 2 0 2 1 0 2 1 2 0 0], 3, 9, 18) + +%% Test input validation +%!error lz77enco (1, 1, 1, 1) diff --git a/inst/matdeintrlv.m b/inst/matdeintrlv.m new file mode 100644 index 0000000..ccb3782 --- /dev/null +++ b/inst/matdeintrlv.m @@ -0,0 +1,36 @@ +## Copyright (C) 2008 Sylvain Pelissier +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{intrlvd} =} matdeintrlv (@var{data}, @var{nrows}, @var{ncols}) +## Restore elements of @var{data} with a temporary matrix of size +## @var{nrows}-by-@var{ncols}. +## @seealso{matintrlv} +## @end deftypefn + +function intrlvd = matdeintrlv (data, Nrows, Ncols) + + if (nargin != 3) + print_usage (); + endif + intrlvd = matintrlv (data, Ncols, Nrows); + +endfunction + +%% Test input validation +%!error matdeintrlv () +%!error matdeintrlv (1) +%!error matdeintrlv (1, 2) +%!error matdeintrlv (1, 2, 3, 4) diff --git a/inst/matintrlv.m b/inst/matintrlv.m new file mode 100644 index 0000000..aecb85b --- /dev/null +++ b/inst/matintrlv.m @@ -0,0 +1,60 @@ +## Copyright (C) 2008 Sylvain Pelissier +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{intrlvd} =} matintrlv (@var{data}, @var{nrows}, @var{ncols}) +## Interleaved elements of @var{data} with a temporary matrix of size +## @var{nrows}-by-@var{ncols}. +## @seealso{matdeintrlv} +## @end deftypefn + +function intrlvd = matintrlv (data, Nrows, Ncols) + + if (nargin != 3) + print_usage (); + endif + + if (! (isscalar (Nrows) && Nrows == fix (Nrows))) + error ("matintrlv: NROWS must be an integer"); + endif + + if (! (isscalar (Ncols) && Ncols == fix (Ncols))) + error ("matintrlv: NCOLS must be an integer"); + endif + + s = size (data); + if (isvector (data)) + if (length (data) != Nrows*Ncols) + error ("matintrlv: DATA must be a vector of length NCOLS*NROWS"); + endif + data = reshape (data, Ncols, Nrows)'; + intrlvd = reshape (data, s); + else + for k = 1:s(2); + if (length (data) != Nrows*Ncols) + error ("matintrlv: DATA must have NCOLS*NROWS rows"); + endif + tmp(:,:,k) = reshape (data(:,k), Ncols, Nrows)'; + intrlvd(:,k) = reshape (tmp(:,:,k), s(1), 1); + endfor + endif + +endfunction + +%% Test input validation +%!error matintrlv () +%!error matintrlv (1) +%!error matintrlv (1, 2) +%!error matintrlv (1, 2, 3, 4) diff --git a/inst/minpol.m b/inst/minpol.m new file mode 100644 index 0000000..e654bf1 --- /dev/null +++ b/inst/minpol.m @@ -0,0 +1,85 @@ +## Copyright (C) 2002 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} minpol (@var{v}) +## +## Finds the minimum polynomial for elements of a Galois Field. For a +## vector @var{v} with @math{N} components, representing @math{N} values +## in a Galois Field GF(2^@var{m}), return the minimum polynomial in GF(2) +## representing those values. +## @end deftypefn + +function r = minpol (v) + + if (nargin != 1) + print_usage (); + endif + + if (!isgalois (v)) + error ("minpol: V must be a Galois field scalar or vector"); + endif + + if (min (size (v)) > 1 || nargin != 1) + print_usage (); + endif + + n = length (v); + m = v.m; + prim_poly = v.prim_poly; + r = zeros (n, m + 1); + + ## Find cosets of GF(2^m) and convert from cell array to matrix + cyclocoset = cosets (m, prim_poly); + cyclomat = zeros (max (size (cyclocoset)), m); + for j = 1:max (size (cyclocoset)) + cyclomat(j,1:length (cyclocoset{j})) = cyclocoset{j}; + endfor + + for j = 1:n + if (v(j) == 0) + ## Special case + r(j,m-1) = 1; + else + ## Find the coset within which the current element falls + [rc, ignored] = find (cyclomat == v(j)); + + rv = cyclomat(rc,:); + + ## Create the minimum polynomial from its roots + ptmp = gf ([1, rv(1)], m, prim_poly); + for i = 2:length (rv) + ptmp = conv (ptmp, [1, rv(i)]); + endfor + + ## Need to left-shift polynomial to divide by x while can + i = 0; + while (!ptmp(m+1-i)) + i = i + 1; + endwhile + ptmp = [zeros(1, i), ptmp(1:m+1-i)]; + r(j,:) = ptmp; + endif + endfor + + ## Ok, now put the return value into GF(2) + r = gf (r, 1); + +endfunction + +%% Test input validation +%!error minpol () +%!error minpol (1) +%!error minpol (1, 2) diff --git a/inst/modmap.m b/inst/modmap.m new file mode 100644 index 0000000..f8ff31a --- /dev/null +++ b/inst/modmap.m @@ -0,0 +1,336 @@ +## Copyright (C) 2003 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} modmap (@var{method}, @dots{}) +## @deftypefnx {Function File} {y =} modmap (@var{x}, @var{fd}, @var{fs}, "ask", @var{m}) +## @deftypefnx {Function File} {y =} modmap (@var{x}, @var{fd}, @var{fs}, "fsk", @var{m}, @var{tone}) +## @deftypefnx {Function File} {y =} modmap (@var{x}, @var{fd}, @var{fs}, "msk") +## @deftypefnx {Function File} {y =} modmap (@var{x}, @var{fd}, @var{fs}, "psk", @var{m}) +## @deftypefnx {Function File} {y =} modmap (@var{x}, @var{fd}, @var{fs}, "qask", @var{m}) +## @deftypefnx {Function File} {y =} modmap (@var{x}, @var{fd}, @var{fs}, "qask/cir", @var{nsig}, @var{amp}, @var{phs}) +## @deftypefnx {Function File} {y =} modmap (@var{x}, @var{fd}, @var{fs}, "qask/arb", @var{inphase}, @var{quadr}) +## @deftypefnx {Function File} {y =} modmap (@var{x}, @var{fd}, @var{fs}, "qask/arb", @var{map}) +## +## Mapping of a digital signal to an analog signal. With no output arguments +## @code{modmap} plots the constellation of the mapping. In this case the +## first argument must be the string @var{method} defining one of "ask", +## "fsk", "msk", "qask", "qask/cir" or "qask/arb". The arguments following +## the string @var{method} are generally the same as those after the +## corresponding string in the function call without output arguments. +## The exception is @code{modmap ("msk", @var{Fd})}. +## +## With an output argument, @var{y} is the complex mapped analog signal. In +## this case the arguments @var{x}, @var{fd} and @var{fs} are required. The +## variable @var{x} is the digital signal to be mapped, @var{fd} is the +## sampling rate of the of digital signal and the @var{fs} is the sampling +## rate of the analog signal. It is required that @code{@var{fs}/@var{fd}} +## is an integer. +## +## The available mapping of the digital signal are +## +## @table @asis +## @item "ask" +## Amplitude shift keying +## @item "fsk" +## Frequency shift keying +## @item "msk" +## Minimum shift keying +## @item "psk" +## Phase shift keying +## @item "qask" +## @itemx "qsk" +## @itemx "qam" +## Quadrature amplitude shift keying +## @end table +## +## In addition the "qask", "qsk" and "qam" method can be modified with the +## flags "/cir" or "/arb". That is "qask/cir" and "qask/arb", etc are valid +## methods and give circular- and arbitrary-qask mappings respectively. +## +## The additional argument @var{m} is the order of the modulation to use. +## @var{m} must be larger than the largest element of @var{x}. The variable +## @var{tone} is the FSK tone to use in the modulation. +## +## For "qask/cir", the additional arguments are the same as for +## @code{apkconst}, and you are referred to @code{apkconst} for the definitions +## of the additional variables. +## +## For "qask/arb", the additional arguments @var{inphase} and @var{quadr} give +## the in-phase and quadrature components of the mapping, in a similar mapping +## to the outputs of @code{qaskenco} with one argument. Similar @var{map} +## represents the in-phase and quadrature components of the mapping as +## the real and imaginary parts of the variable @var{map}. +## @seealso{demodmap, dmodce, amodce, apkconst, qaskenco} +## @end deftypefn + +function y = modmap (varargin) + + method = "sample"; + if (nargout == 0) + if (nargin < 1) + error ("modmap: too few arguments"); + endif + method = varargin{1}; + optarg = 1; + M = 2; + fd = 1; + fs = 1; + elseif (nargout == 1) + if (nargin < 3) + error ("modmap: too few arguments"); + endif + x = varargin{1}; + fd = varargin{2}; + fs = varargin{3}; + if (nargin > 3) + method = varargin{4}; + endif + M = max (2, 2^ceil (log2 (max (x(:)) + 1))); + optarg = 4; + + if (!isscalar (fs) || !isscalar (fd) || !isreal (fs) || !isreal (fd) || ... + (fs <= 0) || (fd <= 0)) + error ("modmap: FD and FS must be positive real values"); + endif + if (abs (fs/fd - fix (fs/fd)) > eps) + error ("modmap: FS must be an integer multiple of FD"); + endif + + nn = round (fs/fd); + if (min (size (x)) == 1) + n = length (x); + yy = zeros (n, 1); + if (size (x, 1) == 1) + yy = yy'; + endif + for i = 1:nn + yy(i:nn:nn*n) = x; + endfor + else + n = size (x, 1); + yy = zeros (n*nn, size (x, 2)); + for i = 1:nn + yy(i:nn:nn*n,:) = x; + endfor + endif + x = yy; + else + error ("modmap: too many output arguments"); + endif + + if (!ischar (method)) + error ("modmap: METHOD must be a string"); + endif + + if (isempty (findstr (method, "/arb")) && isempty (findstr (method, "/cir"))) + if (nargin > optarg) + M = varargin{optarg+1}; + if (! (isscalar (M) && isreal (M) && M == fix (M) && M >= 0)) + error ("modmap: M must be a positive integer"); + endif + endif + if (nargout != 0 && M < max (x(:)) + 1) + error ("modmap: M must be greater than all elements of X"); + endif + endif + + if (strcmp (method, "ask")) + if (nargin > optarg + 1) + error ("modmap: too many arguments"); + endif + + if (nargout == 0) + if (M/2 == floor (M/2)) + apkconst (2*ones (1, M/2), 2*([1:M/2]-0.5)/(M-1)); + else + apkconst ([1, 2*ones(1, floor (M/2))], 2*([0:floor(M/2)])/(M-1)); + endif + else + if (M/2 == floor (M/2)) + c = [-2*([M/2:-1:1]-0.5)/(M-1), 2*([1:M/2]-0.5)/(M-1)]; + else + c = [-2*([floor(M/2):-1:1])/(M-1), 0, 2*([1:floor(M/2)])/(M-1)]; + endif + y = c(x+1); + if (size (x, 2) == 1) + y = y'; + endif + endif + elseif (strcmp (method, "psk")) + if (nargin > optarg + 1) + error ("modmap: too many arguments"); + endif + if (nargout == 0) + apkconst (M, "n"); + else + c = apkconst (M); + y = c(x+1); + if (size (x, 2) == 1) + y = y'; + endif + endif + elseif (strcmp (method, "msk")) + + if (nargout == 0) + if (nargin > optarg) + fd = varargin{optarg+1}; + if (!isscalar (fd)) + error ("modmap: FD must be a scalar"); + endif + endif + if (nargin > optarg + 1) + error ("modmap: too many arguments"); + endif + + ## This is an ugly plot, with little info. But hey!!! + try stem ([0, fd], [2, 1]); + catch + error ("modmap: cannot find stem-plot function"); + end_try_catch + title ("MSK constellation"); + xlabel ("Frequency (Hz)"); + ylabel (""); + axis ([-fd, 2*fd, 0, 2]); + else + if (nargin > optarg) + error ("modmap: too many arguments"); + endif + tone = fd/2; + y = tone * x; + endif + elseif (strcmp (method, "fsk")) + if (nargin > optarg + 1) + tone = varargin{optarg+2}; + if (!isscalar (tone)) + error ("modmap: TONE must be a scalar"); + endif + else + tone = fd; + endif + if (nargin > optarg + 2) + error ("modmap: too many arguments"); + endif + + if (nargout == 0) + ## This is an ugly plot, with little info. But hey!!! + try stem ([0:tone:(M-1)*tone], [2, ones(1, M-1)]); + catch + error ("modmap: can not find stem-plot function"); + end_try_catch + title ("FSK constellation"); + xlabel ("Frequency (Hz)"); + ylabel (""); + axis ([-tone, M*tone, 0, 2]); + else + y = tone * x; + endif + elseif ((strcmp (method, "qask")) || (strcmp (method, "qsk")) || ... + (strcmp (method, "qam"))) + if (nargin > optarg + 1) + error ("modmap: too many arguments"); + endif + if (nargout == 0) + qaskenco (M); + else + y = qaskenco (x, M); + endif + elseif ((strcmp (method, "qask/cir")) || (strcmp (method, "qsk/cir")) || ... + (strcmp (method, "qam/cir"))) + nsig = M; + amp = []; + phs = []; + if (nargin > optarg) + nsig = varargin{optarg+1}; + if (!isvector (nsig) || sum (nsig) < M) + error ("modmap: NSIG must be a vector of M constellation points for METHOD qask/cir"); + endif + endif + if (nargin > optarg + 1) + amp = varargin{optarg+2}; + endif + if (nargin > optarg + 2) + phs = varargin{optarg+3}; + endif + if (nargout == 0) + apkconst (nsig, amp, phs, "n"); + else + c = apkconst (nsig, amp, phs); + y = c(x+1); + if (size (x, 2) == 1) + y = y'; + endif + endif + elseif ((strcmp (method, "qask/arb")) || (strcmp (method, "qsk/arb")) || ... + (strcmp (method, "qam/arb"))) + if (nargin == optarg) + [inphase, quadr] = qaskenco (M); + elseif (nargin == optarg+1) + c = varargin{optarg+1}; + inphase = real (c); + quadr = imag (c); + elseif (nargin == optarg+2) + inphase = varargin{optarg+1}; + quadr = varargin{optarg+2}; + else + error ("modmap: too many arguments"); + endif + if (!isreal (inphase) || !isreal (quadr) || !isvector (inphase) || ... + !isvector (quadr) || !all (isfinite (inphase)) || ... + !all (isfinite (quadr)) || (length (inphase) < M)) + error ("modmap: invalid mapping for METHOD qask/arb"); + endif + + if (nargout == 0) + inphase = inphase(:); + quadr = quadr(:); + plot (inphase, quadr, "+r"); + title ("QASK Constellation"); + xlabel ("In-phase"); + ylabel ("Quadrature"); + axis ([min(inphase) - 1, max(inphase) + 1, min(quadr) - 1, max(quadr) + 1]); + xd = 0.02 * max (inphase); + if (nargin == 2) + msg = msg(:); + for i = 1:length (inphase) + text (inphase(i)+xd, quadr(i), num2str (msg(i))); + endfor + else + for i = 1:length (inphase) + text (inphase(i)+xd, quadr(i), num2str (i-1)); + endfor + endif + refresh; + else + y = inphase(x+1) + 1i * quadr(x+1); + if (size (x, 2) == 1) + y = y'; + endif + endif + elseif (strcmp (method, "sample")) + if (nargout == 0) + error ("modmap: no constellation for resampling"); + endif + ## Just for resampling !!! So don't need anything else here + y = x; + else + error ("modmap: invalid mapping METHOD '%s'", method); + endif + +endfunction + +%% Test input validation +%!error modmap () +%!error modmap (1, 0, 0) diff --git a/inst/oct2dec.m b/inst/oct2dec.m new file mode 100644 index 0000000..27ac18d --- /dev/null +++ b/inst/oct2dec.m @@ -0,0 +1,61 @@ +## Copyright (C) 2007 Sylvain Pelissier +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{d} =} oct2dec (@var{c}) +## +## Convert octal to decimal values. +## +## Each element of the octal matrix @var{c} is converted to a decimal value. +## +## @seealso{base2dec, bin2dec, dec2bin} +## @end deftypefn + +function d = oct2dec (c) + + if (nargin != 1) + print_usage (); + endif + + # Check for negative or non-integer values + if (! (all (c(:) == fix (c(:))) && all (c(:) >= 0))) + error ("oct2dec: C must be an octal matrix"); + endif + + d = zeros (size (c)); + l = size (c, 2); + for k = 1:l + str = num2str (c(:,k), "%ld"); + d(:,k) = base2dec (str, 8); + if (any (isnan (d(:,k)))) + error ("oct2dec: C must be an octal matrix"); + endif + endfor + +endfunction + +%!shared x, y +%! x = reshape ([0:79], 10, 8)(1:8,:); +%! y = reshape ([0:63], 8, 8); +%!assert (oct2dec (0), 0) +%!assert (oct2dec (77777777), 2^24 - 1) +%!assert (oct2dec (x), y) + +%% Test input validation +%!error oct2dec () +%!error oct2dec (0, 0) +%!error oct2dec (0.1) +%!error oct2dec (-1) +%!error oct2dec (8) diff --git a/inst/pamdemod.m b/inst/pamdemod.m new file mode 100644 index 0000000..9df6f6a --- /dev/null +++ b/inst/pamdemod.m @@ -0,0 +1,75 @@ +## Copyright (C) 2006 Charalampos C. Tsimenidis +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{y} =} pamdemod (@var{x}, @var{m}) +## @deftypefnx {Function File} {@var{y} =} pamdemod (@var{x}, @var{m}, @var{phi}) +## @deftypefnx {Function File} {@var{y} =} pamdemod (@var{x}, @var{m}, @var{phi}, @var{type}) +## +## Demodulates a pulse amplitude modulated signal @var{x} into an +## information sequence of integers in the range @code{[0 @dots{} M-1]}. +## @var{phi} controls the initial phase and @var{type} controls the +## constellation mapping. If @var{type} is set to "Bin" will result in +## binary encoding, in contrast, if set to "Gray" will give Gray encoding. +## An example of Gray-encoded 8-PAM is +## +## @example +## @group +## d = randint (1, 1e4, 8); +## y = pammod (d, 8, 0, "gray"); +## z = awgn (y, 20); +## d_est = pamdemod (z, 8, 0, "gray"); +## plot (z, "rx") +## biterr (d, d_est) +## @end group +## @end example +## @seealso{pammod} +## @end deftypefn + +function y = pamdemod (x, M, phi, type) + + if (nargin < 2) + print_usage (); + endif + + if (nargin < 3) + phi = 0; + endif + + if (nargin < 4) + type = "Bin"; + endif + + index = genqamdemod (x, [-M+1:2:M-1] .* exp (-1j*phi)); + + if (strcmp (type, "Bin") || strcmp (type, "bin")) + y = index; + elseif (strcmp (type, "Gray") || strcmp (type, "gray")) + m = 0:M-1; + map = bitxor (m, bitshift (m, -1)); + y = map(index+1); + else + print_usage (); + endif + +endfunction + +%!assert (pamdemod ([-7:2:7], 8, 0, "Bin"), [0:7]) +%!assert (pamdemod ([-7:2:7], 8, 0, "Gray"), [0 1 3 2 6 7 5 4]) + +%% Test input validation +%!error pamdemod () +%!error pamdemod (1) +%!error pamdemod (1, 2, 3, "invalid") diff --git a/inst/pammod.m b/inst/pammod.m new file mode 100644 index 0000000..40ecbea --- /dev/null +++ b/inst/pammod.m @@ -0,0 +1,81 @@ +## Copyright (C) 2006 Charalampos C. Tsimenidis +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{y} =} pammod (@var{x}, @var{m}) +## @deftypefnx {Function File} {@var{y} =} pammod (@var{x}, @var{m}, @var{phi}) +## @deftypefnx {Function File} {@var{y} =} pammod (@var{x}, @var{m}, @var{phi}, @var{type}) +## +## Modulates an information sequence of integers @var{x} in the range +## @code{[0 @dots{} M-1]} onto a pulse amplitude modulated signal @var{y}. +## @var{phi} controls the initial phase and @var{type} controls the +## constellation mapping. If @var{type} is set to "Bin" will result in +## binary encoding, in contrast, if set to "Gray" will give Gray encoding. +## An example of Gray-encoded 8-PAM is +## +## @example +## @group +## d = randint (1, 1e4, 8); +## y = pammod (d, 8, 0, "gray"); +## z = awgn (y, 20); +## plot (z, "rx") +## @end group +## @end example +## @seealso{pamdemod} +## @end deftypefn + +function y = pammod (x, M, phi, type) + + if (nargin < 2) + print_usage (); + endif + + m = 0:M-1; + if (!isempty (find (ismember (x, m) == 0))) + error ("pammod: all elements of X must be integers in the range [0,M-1]"); + endif + + if (nargin < 3) + phi = 0; + endif + + if (nargin < 4) + type = "Bin"; + endif + + constellation = [-M+1:2:M-1] .* exp (-1j*phi); + + if (strcmp (type, "Bin")||strcmp (type, "bin")) + y = constellation(x+1); + elseif (strcmp (type, "Gray")||strcmp (type, "gray")) + [a, b] = sort (bitxor (m, bitshift (m, -1))); + y = constellation(b(x+1)); + else + print_usage (); + endif + + if (iscomplex (y) && all (imag (y(:)) == 0)) + y = real (y); + endif + +endfunction + +%!assert (round (pammod ([0:7], 8, 0, "Bin")), [-7:2:7]) +%!assert (round (pammod ([0:7], 8, 0, "Gray")), [-7 -5 -1 -3 7 5 1 3]) + +%% Test input validation +%!error pammod () +%!error pammod (1) +%!error pammod (1, 2, 3, "invalid") diff --git a/inst/poly2trellis.m b/inst/poly2trellis.m new file mode 100644 index 0000000..7182022 --- /dev/null +++ b/inst/poly2trellis.m @@ -0,0 +1,253 @@ +## Copyright (C) 2012 Mike Miller +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{t} =} poly2trellis (@var{m}, @var{g}) +## +## Convert convolutional code generator polynomials into trellis form. +## +## The arguments @var{m} and @var{g} together describe a rate k/n feedforward +## convolutional encoder. The optional argument @var{f} adds feedback support. +## The output @var{t} is a trellis structure describing +## the same encoder with the fields listed below. +## +## The vector @var{m} is a k-by-1 array containing the lengths of each of the +## shift registers for the k input bits to the encoder. +## +## The matrix @var{g} is a k-by-n octal-value matrix describing the generation +## of each of the n outputs from each of the k inputs. For a particular entry +## of @var{g}, the least-significant bit corresponds to the most-delayed input +## bit in the kth shift-register. +## +## The optional vector @var{f} is a 1-by-k vector of octal numbers describing +## the feedback of each of the shift registers. +## +## The returned trellis structure contains the following fields: +## +## @table @samp +## @item numInputSymbols +## The number of k-bit input symbols possible, i.e. 2^k. +## +## @item numOutputSymbols +## The number of n-bit output symbols possible, i.e. 2^n. +## +## @item numStates +## The number of states in the trellis. +## +## @item nextStates +## The state transition table for the trellis. The ith row contains the indices +## of the states reachable from the (i-1)th state for each possible input +## symbol. +## +## @item outputs +## A table of octal-encoded output values for the trellis. The ith row contains +## values representing the output symbols produced in the (i-1)th state for each +## possible input symbol. +## @end table +## +## Input symbols, output symbols, and encoder states are all interpreted with +## the lowest indices being the most significant bits. +## +## References: +## +## [1] S. Lin and D. J. Costello, "Convolutional codes," in @cite{Error +## Control Coding}, 2nd ed. Upper Saddle River, NJ: Pearson, 2004, +## ch. 11, pp. 453-513. +## +## @seealso{istrellis} +## @end deftypefn + +function t = poly2trellis (m, g, f) + + if ((nargin < 2) || (nargin > 3)) + print_usage (); + endif + + ## Notation agrees with Lin & Costello for the most part: + ## m = length of each modulo-2 adder + ## = 1 + nu(:) = one more than length of each shift register + ## g = generator sequences, k-by-n + ## f = feedback polynomials, 1-by-k vector of octal numbers. + ## k = bits per input symbol = number of shift registers + ## n = bits per output symbol = number of modulo-2 adders + [nr, k] = size (m); + if (nr != 1) + error ("poly2trellis: M must be a 1-by-k positive integer row vector"); + endif + if (! (all (m == fix (m)) && all (m > 0))) + error ("poly2trellis: M must be a 1-by-k positive integer row vector"); + endif + + [nr, n] = size (g); + if (nr != k) + error ("poly2trellis: G must be a k-by-n octal matrix"); + endif + + if (nargin > 2) + [nrf, nf] = size (f); + if (nrf != 1) + error ("poly2trellis: f must be a 1-by-k octal row vector"); + endif + if (nf != k) + error ("poly2trellis: f must be a 1-by-k octal row vector"); + endif + endif + + ## Convert g,f to decimal, let oct2dec validate the octal values + g = oct2dec (g); + if exist('f') + f = oct2dec (f); + ## Error check, feedback includes input bit, or else encoder doesn't work. + if (!all(fix(f./(2.^(m-1))))) + error ("feedback must include input bit"); + endif + endif + + + ## Check the ranges of the generators + ## nu = total number of linear shift registers for all k + nu = sum (m) - k; + + ## Number of states and input symbols needed to capture the state machine + nstates = 2^nu; + ninputs = 2^k; + noutputs = 2^n; + + t = struct ("numInputSymbols", ninputs, + "numOutputSymbols", noutputs, + "numStates", nstates, + "nextStates", zeros (nstates, ninputs), + "outputs", zeros (nstates, ninputs)); + + ## Split state indices into values for each distinct shift register. + ## Also precalculate new bit position for each shift register and the left + ## shifts required to reassemble the states into one state value. + ## + ## Conventions: + ## - Each shift register shifts to the right, MSB-to-LSB + ## - The MSB of each shift register is the newest input + ## - The MSBs of the state represent the k=1 shift register + statebits = de2bi (0:nstates - 1); + states = zeros (nstates, k); + newbit = zeros (1, k); + ##nu = zeros (1, k); + shifts = zeros (1, k); + offset = 1; + for i = 1:k + nu_i = m(i) - 1; + if (nu_i > 0) + states(:,i) = bi2de (statebits(:, offset:offset + nu_i - 1)); + endif + newbit(i) = bitshift (1, nu_i); + shifts(i) = offset - 1; + offset += nu_i; + + if (any (g(i,:) >= 2^m(i))) + error ("poly2trellis: code size is greater than constraint length"); + endif + if (all (g(i,:) < 2^nu_i) || !any (mod (g(i,:), 2))) + error ("poly2trellis: code size is less than constraint length"); + endif + endfor + + ## Generate conversion list of all possible output octal values + outputs = str2num (dec2base (0:noutputs - 1, 8)); + + ## Walk the trellis, each row index is state, each column index is input + for s = 1:nstates + + for i = 1:k + ## For each next input bit [0,1] calculate inputs to modulo-2 adder + ## and the next state for the ith linear shift register, left-shifted + ## to be combined into the total state. + + ## state = states(s,i) + [0; newbit(i)]; + + if exist('f') + ## Handles the state machine feedback, not the input bit. + feedback = mod (sum (de2bi (bitand (f(i), states(s,i))), 2), 2); + else + feedback = 0; + endif + if (!feedback) + ## fb = bitshift (val, nu(i)); + ## Since zero, do as with no feedback + state = states(s,i) + [0; newbit(i)]; + else + ## since 1, added bits flip. + state = states(s,i) + [newbit(i); 0]; + endif + next = bitshift (bitshift (state, -1), shifts(i)); + + ## Calculate the modulo-2 sum of the state plus input for each n for + ## this particular shift register. + ## The MSB of the output represents the n=1 generator(s) + out = [0; 0]; + for adder = 1:n + val = mod (sum (de2bi (bitand (g(i, adder), state)), 2), 2); + out += bitshift (val, n - adder); + endfor + + ## Accumulate contributions to the trellis for this shift register. + ## The contribution to each input symbol depends on whether the + ## (k-i)th bit is 0 or 1. + bitpos = k - i; + for symbol = 1:ninputs + idx = bitget (symbol - 1, bitpos + 1) + 1; + t.nextStates(s, symbol) += next(idx); + t.outputs(s, symbol) = bitxor (t.outputs(s, symbol), out(idx)); + endfor + + endfor + + ## Convert output values to octal representation + t.outputs(s,:) = outputs(t.outputs(s,:) + 1); + + endfor + +endfunction + +%% Test the simple (2,1,3) encoder from Lin & Costello example 11.1 +%!test +%! T = struct ("numInputSymbols", 2, "numOutputSymbols", 4, "numStates", 8, "nextStates", [0 4; 0 4; 1 5; 1 5; 2 6; 2 6; 3 7; 3 7], "outputs", [0 3; 3 0; 3 0; 0 3; 1 2; 2 1; 2 1; 1 2]); +%! t = poly2trellis (4, [13 17]); +%! assert (t, T) +%! assert (istrellis (t), true) + +%% Some additional test cases: + +%!test +%! t = poly2trellis(3,[7 5],7); +%! T = struct ("numInputSymbols", 2, "numOutputSymbols", 4, "numStates", 4, "nextStates", [0 2; 2 0; 3 1; 1 3], "outputs", [0 3; 0 3; 1 2; 1 2]); +%! assert (t, T) +%! assert (istrellis (t), true) + +% Feedback encoder here: +% http://www.mathworks.com/help/comm/ug/error-detection-and-correction.html#fp7431 +%!test +%! t = poly2trellis(5,[37 33],33); +%! T = struct ("numInputSymbols", 2, "numOutputSymbols", 4, "numStates", 16, "nextStates", [0 8; 8 0; 9 1; 1 9; 2 10; 10 2; 11 3; 3 11; 12 4; 4 12; 5 13; 13 5; 14 6; 6 14; 7 15; 15 7], "outputs", [0 3; 0 3; 0 3; 0 3; 2 1; 2 1; 2 1; 2 1; 0 3; 0 3; 0 3; 0 3; 2 1; 2 1; 2 1; 2 1]); +%! assert (t, T) +%! assert (istrellis (t), true) + +%% Test input validation +%!error poly2trellis () +%!error poly2trellis (1, 2, 3) +%!error poly2trellis (1) +%!error poly2trellis (2, 8) +%!error poly2trellis (0, 0) +%!error poly2trellis (2, 0) +%!error poly2trellis (2, 2) +%!error poly2trellis (2, 7) diff --git a/inst/prbs_generator.m b/inst/prbs_generator.m new file mode 100644 index 0000000..bb0559d --- /dev/null +++ b/inst/prbs_generator.m @@ -0,0 +1,72 @@ +## Copyright (C) 2006 Muthiah Annamalai +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{prbs} =} prbs_generator (@var{polynomial}, @var{connections}, @var{initstate}) +## Implement book keeping for a Pseudo-Random Binary Sequence ( PRBS ) +## also called as a Linear Feedback Shift Register. +## +## Given a polynomial create a PRBS structure for that polynomial. +## Now all we need is to just create this polynomial and make it work. +## polynomial must be a vector containing the powers of x and an optional +## value 1. eg: x^3 + x^2 + x + 1 must be written as [3 2 1 0] +## all the coefficients are either 1 or 0. It generates only a Binary \ +## sequence, and the generator polynomial need to be only a binary +## polynomial in GF(2). +## +## connections, contains a struct of vectors where each vector is the +## connection list mapping its vec(2:end) elements to the vec(1) output. +## +## Example: If you had a PRBS shift register like the diagram +## below with 4 registers we use representation by polynomial +## of [ 1 2 3 4], and feedback connections between [ 1 3 4 ]. +## The output PRBS sequence is taken from the position 4. +## +## @example +## @group +## +---+ +----+ +---+ +---+ +## | D |----| D |---| D |---| D | +## +---+ +----+ +---+ +---+ +## | | | +## \ / / +## [+]---------------+------+ +## 1 + 0.D + 1.D^2 + 1.D^3 +## @end group +## @end example +## +## The code to implement this PRBS with a start state of [1 0 1 1] +## will be: +## +## @example +## @group +## prbs = prbs_generator ([1 3 4], @{[1 3 4]@}, [1 0 1 1]); +## x = prbs_sequence (prbs) +## @result{} x = 15 +## prbs_iterator (prbs, 15) +## @result{} [1 1 0 1 0 1 1 1 1 0 0 0 1 0 0] +## @end group +## @end example +## @seealso{prbs_iterator, prbs_sequence} +## @end deftypefn + +function prbs = prbs_generator (polynomial, connections, initstate) + + prbs.reglen = max (polynomial); + prbs.polynomial = polynomial; + prbs.sregs = initstate; + prbs.connections = connections; + prbs.conlen = length (connections); + +endfunction diff --git a/inst/prbs_iterator.m b/inst/prbs_iterator.m new file mode 100644 index 0000000..4c8622f --- /dev/null +++ b/inst/prbs_iterator.m @@ -0,0 +1,162 @@ +## Copyright (C) 2006 Muthiah Annamalai +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {[@var{outputseq}, @var{prbs}] =} prbs_iterator (@var{prbs}, @var{iterations}) +## This function generates the output bits from the PRBS +## state, for the number of iterations specified. +## +## First argument is the PRBS structure obtained from prbs_generator. +## PRBS iterations is specified in the second argument. +## PRBS start state is taken from the prbs.sregs. +## +## Second argument of the output is PRBS structure with a new +## state. This allows usage like: +## +## @example +## [seq, prbs] = prbs_iterator (prbs, niterations); +## @end example +## +## while the state of the PRBS is updated. +## +## Example: If you had a PRBS shift register like the diagram +## below with 4 registers we use representation by polynomial +## of [ 1 2 3 4], and feedback connections between [ 1 3 4 ]. +## The output PRBS sequence is taken from the position 4. +## +## @example +## @group +## +---+ +----+ +---+ +---+ +## | D |----| D |---| D |---| D | +## +---+ +----+ +---+ +---+ +## | | | +## \ / / +## [+]---------------+------+ +## 1 + 0.D + 1.D^2 + 1.D^3 +## @end group +## @end example +## +## The code to implement this PRBS will be +## +## @example +## @group +## prbs = prbs_generator ([1 3 4], @{[1 3 4]@}, [1 0 1 1]); +## x = prbs_iterator (prbs, 15) +## @result{} x = [1 1 0 1 0 1 1 1 1 0 0 0 1 0 0] +## @end group +## @end example +## @seealso{prbs_generator, prbs_sequence} +## @end deftypefn + +function [outputseq, prbs] = prbs_iterator (prbs, iterations = 2^(prbs.reglen)-1) + + if (nargin < 1 || nargin > 2) + print_usage (); + endif + outputseq = zeros (1, iterations); + nstate = zeros (1, prbs.reglen); + + ## For each iteration, shift the output bit. Then compute the xor pattern of connections. + ## Finally apply feedback the stuff. Insert the computed pattern. + for itr = 1:iterations + ## save output. + outputseq(itr) = prbs.sregs(prbs.reglen); + + ## compute the feedback. + for itr2 = 1:prbs.conlen + val = 0; + L = length (prbs.connections{itr2}); + for itr3 = 2:L + val = bitxor (val, prbs.sregs(prbs.connections{itr2}(itr3))); + endfor + nstate(prbs.connections{itr2}(1)) = val; + endfor + + ## rotate the output discarding the last output. + prbs.sregs = [0 prbs.sregs(1:prbs.reglen-1)]; + + ## insert the feedback. + for itr2 = 1:prbs.conlen + prbs.sregs(itr2) = nstate(itr2); + nstate(itr2) = 0; # reset. + endfor + + endfor + +endfunction + +## +## TEST CASES FOR PRBS. +## +## +## 2^31 -1 : D31 + D28 + 1 =0 inverted +## 2^23 -1 : D23 + D18 + 1 = 0 , +## 2^15 -1 : D15 + D14 + 1 = 0, +## 2^10 -1 : D10 + D7 + 1 = 0, +## 2^7 -1 : D7 + D6 + 1 = 0, +## 2^4 -1 : D3 + D2 + 1 = 0, +## +## +---+ +----+ +---+ +---+ +## | D |----| D |---| D |---| D | +## +---+ +----+ +---+ +---+ +## | | | +## \ / / +## [+]---------------+------+ +## 1 + 0.D + 1.D^2 + 1.D^3 +## +## +## prbs=prbs_generator([1 3 4],{[1 3 4]},[1 0 1 1]); +## x = prbs_iterator(prbs,15) +## y = prbs_iterator(prbs,30)(16:end) +## z = prbs_sequence(prbs) +## exit +## break + +## +## Multiple Tap, Simple Sequence Generator. +## +## n=10; +## k=8; +## inits=round(abs(rand(1,n)*1.0)) +## prbs=prbs_generator([n 1],{[1 2 k n-1 n]},inits); +## prbs_iterator(prbs,1023) +## prbs_seqlength(prbs,inits) + +##prbs=prbs_generator([1 2 3],{[1 2 3]},[1 1 1]); +##prbs_iterator(prbs,7) + +## +## 2^4 -1 : D4 + D1 + 1 = 0, +## +## +---+ +----+ +---+ +---+ +## | D |----| D |---| D |---| D | +## +---+ +----+ +---+ +---+ +## | | | +## \ / / +## [+]---------------+------+ +## 1 + 0.D + 1.D^2 + 1.D^3 +## +##prbs=prbs_generator([1 3 4],{[1 2 4]},[1 0 1 1]); +##prbs_iterator(prbs,16) +##prbs_iterator(prbs,32) + + +##prbs=prbs_generator([7],{[1 7 6]},[1 0 0 1 0 0 0]); +##y=prbs_iterator(prbs,128); +##x=prbs_iterator(prbs,256); + +%% Test input validation +%!error prbs_iterator () +%!error prbs_iterator (1, 2, 3) diff --git a/inst/prbs_sequence.m b/inst/prbs_sequence.m new file mode 100644 index 0000000..398306d --- /dev/null +++ b/inst/prbs_sequence.m @@ -0,0 +1,97 @@ +## Copyright (C) 2006 Muthiah Annamalai +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {[@var{itrs}, @var{seq}] =} prbs_sequence (@var{prbs}) +## Implement book keeping for a Pseudo-Random Binary Sequence ( PRBS ) +## also called as a Linear Feedback Shift Register. +## +## For the given PRBS in a intial state, compute the PRBS sequence length. +## Length is period of output when the PRBS state is same as +## the start state of PRBS. +## +## Example: If you had a PRBS shift register like the diagram +## below with 4 registers we use representation by polynomial +## of [ 1 2 3 4], and feedback connections between [ 1 3 4 ]. +## The output PRBS sequence is taken from the position 4. +## +## @example +## @group +## +---+ +----+ +---+ +---+ +## | D |----| D |---| D |---| D | +## +---+ +----+ +---+ +---+ +## | | | +## \ / / +## [+]---------------+------+ +## 1 + 0.D + 1.D^2 + 1.D^3 +## @end group +## @end example +## +## The code to implement this PRBS will be +## +## @example +## @group +## prbs = prbs_generator ([1 3 4], @{[1 3 4]@}, [1 0 1 1]); +## x = prbs_sequence (prbs) +## @result{} x = 15 +## @end group +## @end example +## @seealso{prbs_generator} +## @end deftypefn + +function [itrs, seq] = prbs_sequence (prbs) + + if (nargin != 1) + print_usage (); + endif + nstate = zeros (1, prbs.reglen); + itrs = 0; seq = []; + inits = prbs.sregs; + + ## For each iteration, shift the output bit. Then compute the xor pattern of connections. + ## Finally apply feedback the stuff. Insert the computed pattern. + while (true) + itrs = itrs + 1; + + ## compute the feedback. + for itr2 = 1:prbs.conlen + val = 0; + L = length (prbs.connections{itr2}); + for itr3 = 2:L + val = bitxor (val, prbs.sregs(prbs.connections{itr2}(itr3))); + endfor + nstate(prbs.connections{itr2}(1)) = val; + endfor + + ## rotate the output discarding the last output. + seq = [seq, prbs.sregs(end)]; + prbs.sregs = [0 prbs.sregs(1:prbs.reglen-1)]; + + ## insert the feedback. + for itr2 = 1:prbs.conlen + prbs.sregs(itr2) = nstate(itr2); + nstate(itr2) = 0; # reset. + endfor + + if (isequal (prbs.sregs, inits)) + break + endif + endwhile + +endfunction + +%% Test input validation +%!error prbs_sequence () +%!error prbs_sequence (1, 2) diff --git a/inst/pskdemod.m b/inst/pskdemod.m new file mode 100644 index 0000000..6c312fa --- /dev/null +++ b/inst/pskdemod.m @@ -0,0 +1,75 @@ +## Copyright (C) 2006 Charalampos C. Tsimenidis +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{y} =} pamdemod (@var{x}, @var{m}) +## @deftypefnx {Function File} {@var{y} =} pamdemod (@var{x}, @var{m}, @var{phi}) +## @deftypefnx {Function File} {@var{y} =} pamdemod (@var{x}, @var{m}, @var{phi}, @var{type}) +## +## Demodulates a complex-baseband phase shift keying modulated signal +## into an information sequence of integers in the range +## @code{[0 @dots{} M-1]}. @var{phi} controls the initial phase and +## @var{type} controls the constellation mapping. If @var{type} is set +## to "Bin" will result in binary encoding, in contrast, if set to +## "Gray" will give Gray encoding. An example of Gray-encoded 8-PSK is +## +## @example +## @group +## d = randint (1, 1e3, 8); +## y = pskmod (d, 8, 0, "gray"); +## z = awgn (y, 20); +## d_est = pskdemod (z, 8, 0, "gray"); +## plot (z, "rx") +## biterr (d, d_est) +## @end group +## @end example +## @seealso{pskmod} +## @end deftypefn + +function y = pskdemod (x, M, phi, type) + + if (nargin < 2) + print_usage (); + endif + + if (nargin < 3) + phi = 0; + endif + + if (nargin < 4) + type = "Bin"; + endif + + m = 0:M-1; + index = mod (round ((arg (x) - phi) * M/2/pi), M) + 1; + + if (strcmp (type, "Bin") || strcmp (type, "bin")) + y = index-1; + elseif (strcmp (type, "Gray") || strcmp (type, "gray")) + map = bitxor (m, bitshift (m, -1)); + y = map(index); + else + print_usage (); + endif + +endfunction + +%!assert (pskdemod ([1 j -1 -j], 4, 0, "Bin"), [0:3]) +%!assert (pskdemod ([1 j -j -1], 4, 0, "Gray"), [0:3]) + +%% Test input validation +%!error pskdemod () +%!error pskdemod (1) +%!error pskdemod (1, 2, 3, "invalid") diff --git a/inst/pskmod.m b/inst/pskmod.m new file mode 100644 index 0000000..8136439 --- /dev/null +++ b/inst/pskmod.m @@ -0,0 +1,80 @@ +## Copyright (C) 2006 Charalampos C. Tsimenidis +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{y} =} pskmod (@var{x}, @var{m}) +## @deftypefnx {Function File} {@var{y} =} pskmod (@var{x}, @var{m}, @var{phi}) +## @deftypefnx {Function File} {@var{y} =} pskmod (@var{x}, @var{m}, @var{phi}, @var{type}) +## +## Modulates an information sequence of integers @var{x} in the range +## @code{[0 @dots{} M-1]} onto a complex baseband phase shift keying +## modulated signal @var{y}. @var{phi} controls the initial phase and +## @var{type} controls the constellation mapping. If @var{type} is set +## to "Bin" will result in binary encoding, in contrast, if set to "Gray" +## will give Gray encoding. An example of Gray-encoded QPSK is +## +## @example +## @group +## d = randint (1, 5e3, 4); +## y = pskmod (d, 4, 0, "gray"); +## z = awgn (y, 30); +## plot (z, "rx") +## @end group +## @end example +## @seealso{pskdemod} +## @end deftypefn + +function y = pskmod (x, M, phi, type) + + if (nargin < 2 || nargin > 4) + print_usage (); + endif + + m = 0:M-1; + + if (!isempty (find (ismember (x, m) == 0))) + error ("pskmod: all elements of X must be integers in the range [0,M-1]"); + endif + + if (nargin < 3) + phi = 0; + endif + + if (nargin < 4) + type = "Bin"; + endif + + constellation = exp (1j*2*pi*m/M+1j*phi); + + if (strcmp (type, "Bin") || strcmp (type, "bin")) + y = constellation(x+1); + elseif (strcmp (type, "Gray") || strcmp (type, "gray")) + [a, b] = sort (bitxor (m, bitshift (m, -1))); + y = constellation(b(x+1)); + else + print_usage (); + endif + +endfunction + +%!assert (round (pskmod ([0:3], 4, 0, "Bin")), [1 j -1 -j]) +%!assert (round (pskmod ([0:3], 4, 0, "Gray")), [1 j -j -1]) + +%% Test input validation +%!error pskmod () +%!error pskmod (1) +%!error pskmod (1, 2, 3, 4, 5) +%!error pskmod (1, 2, 3, "invalid") +%!error pskmod (0:7, 4) diff --git a/inst/qamdemod.m b/inst/qamdemod.m new file mode 100644 index 0000000..5598654 --- /dev/null +++ b/inst/qamdemod.m @@ -0,0 +1,48 @@ +## Copyright (C) 2007 Sylvain Pelissier +## Copyright (C) 2009 Christian Neumair +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} qamdemod (@var{x}, @var{m}) +## Create the QAM demodulation of x with a size of alphabet m. +## @seealso{qammod, pskmod, pskdemod} +## @end deftypefn + +function z = qamdemod (y, m) + + if (nargin != 2) + print_usage (); + endif + + c = sqrt (m); + if (! (c == fix (c) && log2 (c) == fix (log2 (c)))) + error ("qamdemod: M must be a square of a power of 2"); + endif + + x = qammod (0:(m-1), m); + x = reshape (x, 1, m); + z = zeros (size (y)); + for k = 1:numel (y) + [n z(k)] = min (abs (y(k) - x)); + endfor + z = z - 1; + +endfunction + +%% Test input validation +%!error qamdemod () +%!error qamdemod (1) +%!error qamdemod (1, 2) +%!error qamdemod (1, 2, 3) diff --git a/inst/qammod.m b/inst/qammod.m new file mode 100644 index 0000000..c8696e7 --- /dev/null +++ b/inst/qammod.m @@ -0,0 +1,51 @@ +## Copyright (C) 2007 Sylvain Pelissier +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} qammod (@var{x}, @var{m}) +## Create the QAM modulation of x with a size of alphabet m. +## @seealso{qamdemod, pskmod, pskdemod} +## @end deftypefn + +function y = qammod (x, m) + + if (nargin != 2) + print_usage (); + endif + + if (any (x >= m)) + error ("qammod: all elements of X must be in the range [0,M-1]"); + endif + + if (!all (x == fix (x))) + error ("qammod: all elements of X must be integers"); + endif + + c = sqrt (m); + if (! (c == fix (c) && log2 (c) == fix (log2 (c)))) + error ("qammod: M must be a square of a power of 2"); + endif + + b = -2 .* mod (x, (c)) + c - 1; + a = 2 .* floor (x ./ (c)) - c + 1; + y = a + i.*b; + +endfunction + +%% Test input validation +%!error qammod () +%!error qammod (1) +%!error qammod (1, 2) +%!error qammod (1, 2, 3) diff --git a/inst/qaskdeco.m b/inst/qaskdeco.m new file mode 100644 index 0000000..b230dd5 --- /dev/null +++ b/inst/qaskdeco.m @@ -0,0 +1,222 @@ +## Copyright (C) 2003 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{msg} =} qaskdeco (@var{c}, @var{m}) +## @deftypefnx {Function File} {@var{msg} =} qaskdeco (@var{inphase}, @var{quadr}, @var{m}) +## @deftypefnx {Function File} {@var{msg} =} qaskdeco (@dots{}, @var{mnmx}) +## +## Demaps an analog signal using a square QASK constellation. The input signal +## maybe either a complex variable @var{c}, or as two real variables +## @var{inphase} and @var{quadr} representing the in-phase and quadrature +## components of the signal. +## +## The argument @var{m} must be a positive integer power of 2. By default the +## same constellation as created in @code{qaskenco} is used by @code{qaskdeco}. +## If is possible to change the values of the minimum and maximum of the +## in-phase and quadrature components of the constellation to account for +## linear changes in the signal values in the received signal. The variable +## @var{mnmx} is a 2-by-2 matrix of the following form +## +## @multitable @columnfractions 0.125 0.05 0.25 0.05 0.25 0.05 +## @item @tab | @tab min in-phase @tab , @tab max in-phase @tab | +## @item @tab | @tab min quadrature @tab , @tab max quadrature @tab | +## @end multitable +## +## If @code{sqrt (@var{m})} is an integer, then @code{qaskenco} uses a Gray +## mapping. Otherwise, an attempt is made to create a nearly square mapping +## with a minimum Hamming distance between adjacent constellation points. +## @seealso{qaskenco} +## @end deftypefn + +function a = qaskdeco (varargin) + + have_mnmx = 0; + if (nargin == 2) + c = varargin{1}; + inphase = real (c); + quadr = imag (c); + M = varargin{2}; + elseif (nargin == 3) + if (all (size (varargin{3}) == [2 2])) + c = varargin{1}; + inphase = real (c); + quadr = imag (c); + M = varargin{2}; + mnmx = varargin{3}; + have_mnmx = 1; + else + inphase = varargin{1}; + quadr = varargin{2}; + M = varargin{3}; + endif + elseif (nargin == 4) + inphase = varargin{1}; + quadr = varargin{2}; + M = varargin{3}; + mnmx = varargin{4}; + have_mnmx = 1; + else + print_usage (); + endif + + if (iscomplex (inphase) || iscomplex (quadr)) + error ("qaskdeco: INPHASE and QUADR must be real"); + endif + + if (!isscalar (M) || M != ceil (M) || M < 2) + error ("qaskdeco: M must be a positive integer greater than 2"); + endif + + if (log2 (M) != ceil (log2 (M))) + error ("qaskdeco: M must be a power of 2"); + endif + + if (have_mnmx) + if (any (size (mnmx) != [2 2])) + error ("qaskdeco: MNMX must be a 2-by-2 matrix of min and max values"); + endif + else + if ((M == 2) || (M == 4)) + mnmx = [-1, 1; -1, 1]; + elseif (M == 8) + mnmx = [-3, 3; -1, 1]; + elseif (sqrt (M) == fix (sqrt (M))) + NC = 2^floor (log2 (sqrt (M))); + mnmx = [-NC+1, NC-1; -NC+1, NC-1]; + else + NC = 2^floor (log2 (sqrt (M))) + 2*sqrt (M/32); + mnmx = [-NC+1, NC-1; -NC+1, NC-1]; + endif + endif + + if (M == 2) + layout = [0, 1]'; + elseif (M == 4) + layout = [0, 1; 2, 3]; + elseif (M == 8) + layout = [4, 5; 0, 1; 2, 3; 6, 7]; + else + NC = 2^floor (log2 (sqrt (M))); + MM = NC * NC; + Gray = [0 1]; + for i = 2:ceil (log2 (NC)) + Gray = [Gray 2^(i-1) + fliplr(Gray)]; + endfor + Gray = fliplr (de2bi (shift (Gray, length (Gray)/2 - 1))); + Gray2 = zeros (MM, log2 (MM)); + Gray2(:,1:2:log2 (MM)) = repmat (Gray, NC, 1); + for i = 1:NC + Gray2(i:NC:MM,2:2:log2 (MM)) = Gray; + endfor + layout = reshape (bi2de (fliplr (Gray2)), NC, NC); + + if (MM != M) + ## Not sure this is the best that can be done for these mappings. If + ## anyone wants to improve this, go ahead, but do it in qaskenco too. + OFF = sqrt (M/32); + NR = NC + 2*OFF; + layout2 = NaN * ones (NR); + layout2(1+OFF:OFF+NC,1+OFF:OFF+NC) = layout; + + layout2(1:OFF,1+OFF:OFF+NC) = MM + layout(OFF:-1:1,:); + layout2(NR-OFF+1:NR,1+OFF:OFF+NC) = MM + layout(NC:-1:NC-OFF+1,:); + + layout2(1+2*OFF:NC,1:OFF) = MM + layout(OFF+1:NC-OFF,OFF:-1:1); + layout2(1+2*OFF:NC,NR-OFF+1:NR) = MM + ... + layout(OFF+1:NC-OFF,NC:-1:NC-OFF+1); + + layout2(1+OFF:2*OFF,1:OFF) = MM + ... + layout(NC/2:-1:NC/2-OFF+1,NC/2:-1:OFF+1); + layout2(NC+1:OFF+NC,1:OFF) = MM + ... + layout(NC-OFF:-1:NC/2+1,NC/2:-1:OFF+1); + + layout2(1+OFF:2*OFF,NR-OFF+1:NR) = MM + ... + layout(NC/2:-1:NC/2-OFF+1,NC-OFF:-1:NC/2+1); + layout2(NC+1:OFF+NC,NR-OFF+1:NR) = MM + ... + layout(NC-OFF:-1:NC/2+1,NC-OFF:-1:NC/2+1); + layout = layout2; + endif + endif + + ix = 1 + (inphase - mnmx(1,1)) / (mnmx(1,2)-mnmx(1,1)) * (size (layout, 1) - 1); + qx = 1 + (quadr - mnmx(2,1)) / (mnmx(2,2)-mnmx(2,1)) * (size (layout, 2) - 1); + + try wfi = warning ("off", "Octave:fortran-indexing"); + catch wfi = 0; + end_try_catch + + unwind_protect + a = layout(size (layout, 1) * (max (min (round (qx), size (layout, 2)), 1) - 1) + ... + max (min (round (ix), size (layout, 1)), 1)); + ## FIXME: Why is this necessary?? + if ((M == 2) && (size (inphase, 1) == 1)) + a = a'; + endif + + if (any (isnan (a(:)))) + ## We have a non-square constellation, with some invalid points. + ## Map to nearest valid constellation points... + indx = find (isnan (a(:))); + ix = ix(indx); + qx = qx(indx); + ang = atan2 (quadr(indx), inphase(indx)); + + qx(find (ang > 3*pi/4)) = NR-OFF; + ix(find ((ang <= 3*pi/4) & (ang > pi/2))) = OFF+1; + ix(find ((ang <= pi/2) & (ang > pi/4))) = NR - OFF; + qx(find ((ang <= pi/4) & (ang > 0))) = NR - OFF; + qx(find ((ang <= 0) & (ang > -pi/4))) = OFF+1; + ix(find ((ang <= -pi/4) & (ang > -pi/2))) = NR - OFF; + ix(find ((ang <= -pi/2) & (ang > -3*pi/4))) = OFF+1; + qx(find (ang <= -3*pi/4)) = OFF+1; + + a(indx) = layout(size (layout, 1) * (max (min (round (qx), ... + size (layout, 2)), 1)-1) + max (min (round (ix), size (layout, 1)), 1)); + endif + unwind_protect_cleanup + warning (wfi); + end_unwind_protect + +endfunction + +%!function dec = __fntestqask1__ (msg, m) +%! [inp, qudr] = qaskenco (msg, m); +%! dec = qaskdeco (inp, qudr, m); + +%!function __fntestqask2__ (m, dims) +%! msg = floor (rand (dims) * m); +%! assert (__fntestqask1__ (msg, m), msg); + +%!test __fntestqask2__ (2, [100, 100]) +%!test __fntestqask2__ (4, [100, 100]) +%!test __fntestqask2__ (8, [100, 100]) +%!test __fntestqask2__ (16, [100, 100]) +%!test __fntestqask2__ (32, [100, 100]) +%!test __fntestqask2__ (64, [100, 100]) + +%!test __fntestqask2__ (2, [100, 100, 3]) +%!test __fntestqask2__ (4, [100, 100, 3]) +%!test __fntestqask2__ (8, [100, 100, 3]) +%!test __fntestqask2__ (16, [100, 100, 3]) +%!test __fntestqask2__ (32, [100, 100, 3]) +%!test __fntestqask2__ (64, [100, 100, 3]) + +%% Test input validation +%!error qaskdeco () +%!error qaskdeco (1) +%!error qaskdeco (1, 2, 3, 4, 5) +%!error qaskdeco (1, 1) +%!error qaskdeco (1, 5) diff --git a/inst/qaskenco.m b/inst/qaskenco.m new file mode 100644 index 0000000..3b76321 --- /dev/null +++ b/inst/qaskenco.m @@ -0,0 +1,182 @@ +## Copyright (C) 2003 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} qaskenco (@var{m}) +## @deftypefnx {Function File} {} qaskenco (@var{msg}, @var{m}) +## @deftypefnx {Function File} {@var{y} =} qaskenco (@dots{}) +## @deftypefnx {Function File} {[@var{inphase}, @var{quadr}] =} qaskenco (@dots{}) +## +## Map a digital signal using a square QASK constellation. The argument +## @var{m} must be a positive integer power of 2. With two input arguments +## the variable @var{msg} represents the message to be encoded. The values +## of @var{msg} must be between 0 and @code{@var{m}-1}. In all cases +## @code{qaskenco (@var{M})} is equivalent to @code{qaskenco (1:@var{m}, @var{m})} +## +## Three types of outputs can be created depending on the number of output +## arguments. That is +## +## @table @asis +## @item No output arguments +## In this case @code{qaskenco} plots the constellation. Only the +## points in @var{msg} are plotted, which in the case of a single input +## argument is all constellation points. +## @item A single output argument +## The returned variable is a complex variable representing the in-phase +## and quadrature components of the mapped message @var{msg}. With, a +## single input argument this effectively gives the mapping from symbols +## to constellation points +## @item Two output arguments +## This is the same as one output argument, expect that the in-phase +## and quadrature components are returned explicitly. That is +## +## @example +## c = qaskenco (msg, m); +## [a, b] = qaskenco (msg, m); +## all (c == a + 1i*b) +## @result{} 1 +## @end example +## @end table +## +## If @code{sqrt (@var{m})} is an integer, then @code{qaskenco} uses a Gray +## mapping. Otherwise, an attempt is made to create a nearly square mapping +## with a minimum Hamming distance between adjacent constellation points. +## @seealso{qaskdeco} +## @end deftypefn + +function [a, b] = qaskenco (msg, M) + + if (nargin == 1) + M = msg; + elseif (nargin == 2) + if (min (msg(:)) < 0 || max (msg(:)) > M-1) + error ("qaskenco: all elements of MSG must be in the range [0:M-1]"); + endif + else + print_usage (); + endif + + if (!isscalar (M) || M != ceil (M) || M < 2) + error ("qaskenco: M must be a positive integer greater than 2"); + endif + + if (log2 (M) != ceil (log2 (M))) + error ("qaskenco: M must be a power of 2"); + endif + + if (M == 2) + inphase = [-1, 1]; + quadr = [ 0, 0]; + elseif (M == 4) + inphase = [-1, -1, 1, 1]; + quadr = [-1, 1, -1, 1]; + elseif (M == 8) + inphase = [-1, -1, 1, 1, -3, -3, 3, 3]; + quadr = [-1, 1, -1, 1, -1, 1, -1, 1]; + else + NC = 2^floor (log2 (sqrt (M))); + MM = NC * NC; + Gray = [0, 1]; + for i = 2:ceil (log2 (NC)) + Gray = [Gray 2^(i-1) + fliplr(Gray)]; + endfor + Gray = fliplr (de2bi (shift (Gray, length (Gray)/2 - 1))); + Gray2 = zeros (MM, log2 (MM)); + Gray2(:,1:2:log2 (MM)) = repmat (Gray, NC, 1); + for i = 1:NC + Gray2(i:NC:MM,2:2:log2 (MM)) = Gray; + endfor + layout = reshape (bi2de (fliplr (Gray2)), NC, NC); + + if (MM != M) + ## Not sure this is the best that can be done for these mappings. If + ## anyone wants to improve this, go ahead, but do it in qaskdeco too. + OFF = sqrt (M/32); + NR = NC + 2*OFF; + layout2 = NaN * ones (NR); + layout2(1+OFF:OFF+NC,1+OFF:OFF+NC) = layout; + + layout2(1:OFF,1+OFF:OFF+NC) = MM + layout(OFF:-1:1,:); + layout2(NR-OFF+1:NR,1+OFF:OFF+NC) = MM + layout(NC:-1:NC-OFF+1,:); + + layout2(1+2*OFF:NC,1:OFF) = MM + layout(OFF+1:NC-OFF,OFF:-1:1); + layout2(1+2*OFF:NC,NR-OFF+1:NR) = MM + ... + layout(OFF+1:NC-OFF,NC:-1:NC-OFF+1); + + layout2(1+OFF:2*OFF,1:OFF) = MM + ... + layout(NC/2:-1:NC/2-OFF+1,NC/2:-1:OFF+1); + layout2(NC+1:OFF+NC,1:OFF) = MM + ... + layout(NC-OFF:-1:NC/2+1,NC/2:-1:OFF+1); + + layout2(1+OFF:2*OFF,NR-OFF+1:NR) = MM + ... + layout(NC/2:-1:NC/2-OFF+1,NC-OFF:-1:NC/2+1); + layout2(NC+1:OFF+NC,NR-OFF+1:NR) = MM + ... + layout(NC-OFF:-1:NC/2+1,NC-OFF:-1:NC/2+1); + NC = NR; + layout = layout2; + endif + + inphase = repmat ([0:NC-1]*2 - NC + 1, 1, NC); + for i = 1:NC + quadr(i:NC:NC*NC) = [0:NC-1]*2 - NC + 1; + endfor + [dummy, indx] = sort (layout(:)); + indx = indx(1:M); ## Get rid of remaining NaN's + inphase = inphase(indx); + quadr = quadr(indx); + endif + + if (nargin == 2) + inphase = inphase(msg+1); + quadr = quadr(msg+1); + ## Fix up indexing if using column vector + if (size (msg, 2) == 1) + inphase = inphase'; + quadr = quadr'; + endif + endif + + if (nargout == 0) + inphase = inphase(:); + quadr = quadr(:); + plot (inphase, quadr, "r+"); + title ("QASK Constellation"); + xlabel ("In-phase"); + ylabel ("Quadrature"); + axis ([min(inphase) - 1, max(inphase) + 1, min(quadr) - 1, max(quadr) + 1]); + xd = 0.02 * max (inphase); + if (nargin == 2) + msg = msg(:); + for i = 1:length (inphase) + text (inphase(i) + xd, quadr(i), num2str (msg(i))); + endfor + else + for i = 1:length (inphase) + text (inphase(i) + xd, quadr(i), num2str (i-1)); + endfor + endif + elseif (nargout == 1) + a = inphase + 1i * quadr; + else + a = inphase; + b = quadr; + endif + +endfunction + +%% Test input validation +%!error qaskenco () +%!error qaskenco (1, 2, 3) +%!error qaskenco (0:7, 3) diff --git a/inst/qfunc.m b/inst/qfunc.m new file mode 100644 index 0000000..96ac030 --- /dev/null +++ b/inst/qfunc.m @@ -0,0 +1,36 @@ +## Copyright (C) 2007 Sylvain Pelissier +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{y} =} qfunc (@var{x}) +## Compute the Q function. +## @seealso{erfc, erf} +## @end deftypefn + +function y = qfunc (x) + + if (nargin != 1) + print_usage (); + endif + + y = erfc (x / sqrt(2)) / 2; + +endfunction + +%!assert (qfunc ([-Inf 0 Inf]), [1 0.5 0]) + +%% Test input validation +%!error qfunc () +%!error qfunc (1, 2) diff --git a/inst/qfuncinv.m b/inst/qfuncinv.m new file mode 100644 index 0000000..387c25a --- /dev/null +++ b/inst/qfuncinv.m @@ -0,0 +1,35 @@ +## Copyright (C) 2007 Sylvain Pelissier +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{y} =} qfuncinv (@var{x}) +## Compute the inverse Q function. +## @seealso{erfc, erf} +## @end deftypefn + +function y = qfuncinv (x) + + if (nargin != 1) + print_usage (); + endif + y = sqrt(2)*erfcinv(2*x); + +endfunction + +%!assert (qfuncinv ([0 0.5 1]), [Inf 0 -Inf]) + +%% Test input validation +%!error qfuncinv () +%!error qfuncinv (1, 2) diff --git a/inst/quantiz.m b/inst/quantiz.m new file mode 100644 index 0000000..e6e2fca --- /dev/null +++ b/inst/quantiz.m @@ -0,0 +1,71 @@ +## Copyright (C) 2001 Paul Kienzle +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{qidx} =} quantiz (@var{x}, @var{table}) +## @deftypefnx {Function File} {[@var{qidx}, @var{q}] =} quantiz (@var{x}, @var{table}, @var{codes}) +## @deftypefnx {Function File} {[ @var{qidx}, @var{q}, @var{d}] =} quantiz (@dots{}) +## +## Quantization of an arbitrary signal relative to a partitioning. +## +## @table @code +## @item qidx = quantiz (x, table) +## Determine position of x in strictly monotonic table. The first +## interval, using index 0, corresponds to x <= table(1). +## Subsequent intervals are table(i-1) < x <= table(i). +## +## @item [qidx, q] = quantiz (x, table, codes) +## Associate each interval of the table with a code. Use codes(1) +## for x <= table(1) and codes(n+1) for table(n) < x <= table(n+1). +## +## @item [qidx, q, d] = quantiz (...) +## Compute distortion as mean squared distance of x from the +## corresponding quantization values. +## @end table +## @end deftypefn + +function [qidx, q, d] = quantiz (x, table, codes) + + if (nargin < 2 || nargin > 3) + print_usage (); + endif + + if (numel (table) == 1) + qidx = double (table < x); + else + qidx = length (table) - lookup (flipud (table(:)), x); + endif + + if (nargin > 2 && nargout > 1) + q = codes(qidx + 1); + endif + if (nargout > 2) + table = [table(1) ; table(:) ]; + d = sumsq (x(:) - q(:)) / length (x); + endif + +endfunction + +%!assert (quantiz (1:10, 0:9), 1:10); +%!assert (quantiz ([1:10]', 0:9), [1:10]'); +%!assert (quantiz (1:10, [3 6 9]), [0 0 0 1 1 1 2 2 2 3]); +%!assert (quantiz (1:10, 5), [0 0 0 0 0 1 1 1 1 1]); +%!assert (quantiz ([-Inf -1 0 1 Inf], [-1 0 1]), [0 0 1 2 3]); +%!assert (quantiz ([-Inf -1 0 1 Inf], 0), [0 0 0 1 1]); + +%% Test input validation +%!error quantiz () +%!error quantiz (1) +%!error quantiz (1, 2, 3, 4) diff --git a/inst/randdeintrlv.m b/inst/randdeintrlv.m new file mode 100644 index 0000000..7460696 --- /dev/null +++ b/inst/randdeintrlv.m @@ -0,0 +1,41 @@ +## Copyright (C) 2008 Sylvain Pelissier +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{intrlvd} =} randdeintrlv (@var{data}, @var{state}) +## Restore elements of @var{data} with a random permutation. +## @seealso{randintrlv, intrlv, deintrlv} +## @end deftypefn + +function deintrlvd = randdeintrlv (data, state) + + if (nargin != 2) + print_usage (); + endif + + if (isvector (data)) + l = length (data); + else + l = size (data, 1); + endif + rand ("state", state); + deintrlvd = deintrlv (data, randperm (l)); + +endfunction + +%% Test input validation +%!error randdeintrlv () +%!error randdeintrlv (1) +%!error randdeintrlv (1, 2, 3) diff --git a/inst/randerr.m b/inst/randerr.m new file mode 100644 index 0000000..ec3d3d0 --- /dev/null +++ b/inst/randerr.m @@ -0,0 +1,114 @@ +## Copyright (C) 2003 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{b} =} randerr (@var{n}) +## @deftypefnx {Function File} {@var{b} =} randerr (@var{n}, @var{m}) +## @deftypefnx {Function File} {@var{b} =} randerr (@var{n}, @var{m}, @var{err}) +## @deftypefnx {Function File} {@var{b} =} randerr (@var{n}, @var{m}, @var{err}, @var{seed}) +## +## Generate a matrix of random bit errors. The size of the matrix is +## @var{n} rows by @var{m} columns. By default @var{m} is equal to @var{n}. +## Bit errors in the matrix are indicated by a 1. +## +## The variable @var{err} determines the number of errors per row. By +## default the return matrix @var{b} has exactly one bit error per row. +## If @var{err} is a scalar, there each row of @var{b} has exactly this +## number of errors per row. If @var{err} is a vector then each row has +## a number of errors that is in this vector. Each number of errors has +## an equal probability. If @var{err} is a matrix with two rows, then +## the first row determines the number of errors and the second their +## probabilities. +## +## The variable @var{seed} allows the random number generator to be seeded +## with a fixed value. The initial seed will be restored when returning. +## @end deftypefn + +function b = randerr (n, m, err, seed) + + switch (nargin) + case 0 + m = 1; + n = 1; + err = 1; + seed = Inf; + case 1 + m = n; + err = 1; + seed = Inf; + case 2 + err = 1; + seed = Inf; + case 3 + seed = Inf; + case 4 + otherwise + print_usage (); + endswitch + + ## Check error vector + [ar, ac] = size (err); + if (ac == 1) + if (ar > 1) + err = err'; + endif + elseif ((ac > 1) && (ar != 1) && (ar != 2)) + error ("randerr: ERR must be a scalar, a vector, or a matrix with 2 rows"); + endif + for i = 1:ac + if (err(1,i) > m) + error ("randerr: number of errors in ERR must be no greater than M"); + endif + endfor + + # Use randsrc to calculate the number of errors per row + nerrs = randsrc (n, 1, err, seed); + + # Now put to errors into place in the return matrix + b = zeros (n, m); + for i = 1:n + if (nerrs(i) > 0) + if (nerrs(i) == 1) + indx = sort (randint (1, nerrs(i), m, seed)); + else + do + indx = sort (randint (1, nerrs(i), m, seed)); + until (! any (indx(1:nerrs(i)-1) == indx(2:nerrs(i)))) + endif + b(i,indx+1) = ones (1, nerrs(i)); + endif + endfor + +endfunction + +%!shared n, err1, err2, seed, a1, a2, a3, a4, a5, a6 +%! n = 10; err1 = 2; err2 = [1, 2; 0.7, 0.3] ; seed = 1; +%! a1 = randerr (n); a2 = randerr (n, n); +%! a3 = randerr (n, n, err1); a4 = randerr (n, n, err2); +%! a5 = randerr (n, n, err1, seed); a6 = randerr (n, n, err1, seed); + +%!error randerr (n, n, n, n, n); +%!assert (size (a1) == [n, n] && size (a2) == [n, n]); +%!assert (all (sum (a1.') == 1) && all (sum (a2.') == 1)) +%!assert (all ((a1(:) == 1 | a1(:) == 0)) && all ((a2(:) == 1 | a2(:) == 0))) +%!assert (size (a3) == [n, n] && size (a4) == [n, n]); +%!assert (all (sum (a3.') == err1)) +%!assert (all ((a3(:) == 1 | a3(:) == 0))) +%!assert (all ((sum (a4.') == err2(1,1)) | (sum (a4.') == err2(1,2)))) +%!assert (all ((a4(:) == 1 | a4(:) == 0))) +%!assert (a5(:) == a6(:)); + +%% Test input validation +%!error randerr (1, 2, 3, 4, 5) diff --git a/inst/randint.m b/inst/randint.m new file mode 100644 index 0000000..b44fcac --- /dev/null +++ b/inst/randint.m @@ -0,0 +1,100 @@ +## Copyright (C) 2001 Laurent Mazet +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{b} =} randint (@var{n}) +## @deftypefnx {Function File} {@var{b} =} randint (@var{n}, @var{m}) +## @deftypefnx {Function File} {@var{b} =} randint (@var{n}, @var{m}, @var{range}) +## @deftypefnx {Function File} {@var{b} =} randint (@var{n}, @var{m}, @var{range}, @var{seed}) +## +## Generate a matrix of random binary numbers. The size of the matrix is +## @var{n} rows by @var{m} columns. By default @var{m} is equal to @var{n}. +## +## The range in which the integers are generated will is determined by +## the variable @var{range}. If @var{range} is an integer, the value will +## lie in the range [0,@var{range}-1], or [@var{range}+1,0] if @var{range} +## is negative. If @var{range} contains two elements the integers will lie +## within these two elements, inclusive. By default @var{range} is +## assumed to be [0:1]. +## +## The variable @var{seed} allows the random number generator to be seeded +## with a fixed value. The initial seed will be restored when returning. +## @end deftypefn + +function b = randint (n, m, range, seed) + + switch (nargin) + case 1 + m = n; + range = [0, 1]; + seed = Inf; + case 2 + range = [0, 1]; + seed = Inf; + case 3 + seed = Inf; + case 4 + otherwise + print_usage (); + endswitch + + ## Check range + if (length (range) == 1) + if (range < 0) + range = [range+1, 0]; + else + range = [0, range-1]; + endif + elseif ( prod (size (range)) != 2) + error ("randint: RANGE must be a scalar or a 2-element vector"); + endif + range = sort (range); + + ## Check seed; + if (!isinf (seed)) + old_seed = rand ("seed"); + rand ("seed", seed); + endif + + b = range (1) - 1 + ceil (rand (n, m) * (range (2) - range (1) + 1)); + + ## Get back to the old + if (!isinf (seed)) + rand ("seed", old_seed); + endif + +endfunction + +%!shared n, m, seed, a1, a2, a3, a4, a5, a6 +%! n = 10; m = 32; seed = 1; a1 = randint (n); a2 = randint (n, n); +%! a3 = randint (n, n, m); a4 = randint (n, n, [-m, m]); +%! a5 = randint (n, n, m, seed); a6 = randint (n, n, m, seed); + +%!error randint (); +%!error randint (n, n, n, n, n); +%!assert (size (a1) == [n, n] && size (a2) == [n, n]); +%!assert (max ([a1(:); a2(:)]) <= 1 && min ([a1(:); a2(:)]) >= 0); +%!assert (size (a3) == [n, n] && size (a4) == [n, n]); +%!assert (max (a3(:)) < m && min (a3(:)) >= 0); +%!assert (max (a4(:)) <= m && min (a4(:)) >= -m); +%!assert (a5(:) == a6(:)); + +%!test +%! a = randint (10, 10, -32); +%! assert (max (a(:)) <= 0 && min (a(:)) > -32); + +%% Test input validation +%!error randint (1, 2, 3, 4, 5) +%!error randint (1, 1, [1 2 3]) diff --git a/inst/randintrlv.m b/inst/randintrlv.m new file mode 100644 index 0000000..0b6ab27 --- /dev/null +++ b/inst/randintrlv.m @@ -0,0 +1,41 @@ +## Copyright (C) 2008 Sylvain Pelissier +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{intrlvd} =} randintrlv (@var{data}, @var{state}) +## Interleaves elements of @var{data} with a random permutation. +## @seealso{intrlv, deintrlv} +## @end deftypefn + +function intrlvd = randintrlv (data, state) + + if (nargin != 2) + print_usage (); + endif + + if (isvector (data)) + l = length (data); + else + l = size (data, 1); + endif + rand ("state", state); + intrlvd = intrlv (data, randperm (l)); + +endfunction + +%% Test input validation +%!error randintrlv () +%!error randintrlv (1) +%!error randintrlv (1, 2, 3) diff --git a/inst/randsrc.m b/inst/randsrc.m new file mode 100644 index 0000000..97febaa --- /dev/null +++ b/inst/randsrc.m @@ -0,0 +1,122 @@ +## Copyright (C) 2003 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{b} =} randsrc (@var{n}) +## @deftypefnx {Function File} {@var{b} =} randsrc (@var{n}, @var{m}) +## @deftypefnx {Function File} {@var{b} =} randsrc (@var{n}, @var{m}, @var{alphabet}) +## @deftypefnx {Function File} {@var{b} =} randsrc (@var{n}, @var{m}, @var{alphabet}, @var{seed}) +## +## Generate a matrix of random symbols. The size of the matrix is +## @var{n} rows by @var{m} columns. By default @var{m} is equal to @var{n}. +## +## The variable @var{alphabet} can be either a row vector or a matrix with +## two rows. When @var{alphabet} is a row vector the symbols returned in +## @var{b} are chosen with equal probability from @var{alphabet}. When +## @var{alphabet} has two rows, the second row determines the probability +## with which each of the symbols is chosen. The sum of the probabilities +## must equal 1. By default @var{alphabet} is [-1 1]. +## +## The variable @var{seed} allows the random number generator to be seeded +## with a fixed value. The initial seed will be restored when returning. +## @end deftypefn + +function b = randsrc (n, m, alphabet, seed) + + switch (nargin) + case 0 + m = 1; + n = 1; + alphabet = [-1, 1]; + seed = Inf; + case 1 + m = n; + alphabet = [-1, 1]; + seed = Inf; + case 2 + alphabet = [-1, 1]; + seed = Inf; + case 3 + seed = Inf; + case 4 + otherwise + print_usage (); + endswitch + + ## Check alphabet + [ar, ac] = size (alphabet); + if (ac == 1) + b = alphabet (1, 1) * ones (n, m); + return; + endif + + if (ar == 1) + prob = [1:ac] / ac; + elseif (ar == 2) + prob = alphabet(2,:); + alphabet = alphabet(1,:); + if (abs (1 - sum (prob)) > eps) + error ("randsrc: the probabilities of ALPHABET must add up to 1"); + endif + prob = cumsum (prob); + else + error ("randsrc: ALPHABET must be a vector or a matrix with 2 rows"); + endif + + ## Check seed; + if (!isinf (seed)) + old_seed = rand ("seed"); + rand ("seed", seed); + endif + + ## Create indexes with the right probabilities + tmp = rand (n, m); + b = ones (n, m); + for i = 1:ac-1 + b = b + (tmp > prob(i)); + endfor + + ## Map the indexes to the symbols + b = alphabet(b); + + ## BUG: the above gives a row vector for some reason. Force what we want + b = reshape (b, n, m); + + ## Get back to the old + if (!isinf (seed)) + rand ("seed", old_seed); + endif + +endfunction + +%!shared n, alph1, alph2, seed, a1, a2, a3, a4, a5, a6 +%! n = 10; alph1 = [0, 1; 0.3, 0.7]; alph2 = ["a", "b"]; seed = 1; +%! a1 = randsrc (n); a2 = randsrc (n, n); +%! a3 = randsrc (n, n, alph1); a4 = randsrc (n, n, alph2); +%! a5 = randsrc (n, n, alph1, seed); a6 = randsrc (n, n, alph1, seed); + +%!error randsrc (n, n, n, n, n); +%!assert (size (a1) == [n, n] && size (a2) == [n, n]); +%!assert (max ([a1(:); a2(:)]) <= 1 && min ([a1(:); a2(:)]) >= -1); +%!assert (size (a3) == [n, n] && size (a4) == [n, n]); +%!assert (max (a3(:)) <= 1 && min (a3(:)) >= 0); +%!assert (max (double (a4(:))) <= double ("b")) +%!assert (max (double (a4(:))) >= double ("a")) +%!assert (a5(:) == a6(:)); + +%% Test input validation +%!error randsrc (1, 2, 3, 4, 5) +%!error randsrc (1, 1, ones (3)) +%!error randsrc (1, 1, [0 1 2; 0.5 0.5 0.5]) diff --git a/inst/rcosfir.m b/inst/rcosfir.m new file mode 100644 index 0000000..794de57 --- /dev/null +++ b/inst/rcosfir.m @@ -0,0 +1,141 @@ +## Copyright (C) 2016 Oscar Monerris Belda +## +## This program is free software; you can redistribute it and/or modify it +## under the terms of the GNU General Public License as published by +## the Free Software Foundation; either version 3 of the License, or +## (at your option) any later version. +## +## This program 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 General Public License for more details. +## +## You should have received a copy of the GNU General Public License +## along with this program. If not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{h}, @var{st} =} rcosfir(@var{R},@var{nT},@var{rate},@var{T},@var{filterType}) +## +## Implements a cosine filter or root cosine filter impulse response +## +## @var{R} Roll-off factor +## +## @var{nT} scalar vector of length 2 such as N = (nT(2)-nT(1))*rate+1 +## +## @var{T} symbol rate +## +## @var{filterType} 'normal' or 'sqrt' +## +## @var{h} impulse response +## +## @var{st} sampling interval +## +## Example: +## +## h = rcosfir(0.2,[-3 3],4,1,'sqrt'); +## @seealso{filter, downsample, rectfilt} +## @end deftypefn + +## Author: Oscar Monerris Belda +## Created: 2016-05-29 + +function [h, st] = rcosfir(R,nT,rate,T,filterType) + + +if (nargin < 1) + error('rcosfir: Not enough input arguments'); +elseif (nargin == 1) + nT=[-3 3]; + rate=5; + T=1; + filterType ='normal'; +elseif (nargin == 2) + rate=5; + T=1; + filterType ='normal'; +elseif (nargin == 3) + T=1; + filterType ='normal'; +elseif (nargin == 4) + filterType ='normal'; +end +if (numel(nT) == 1) + nT = [-nT nT]; +end + +if (fix(rate) ~= rate || rate < 1) + error('rcosfir: rate must be an integer greater than 1') +end + +if (numel(nT) ~= 2) + error('rcosfir: nT must be a two elements vector') +end + +if (T < 0) + error('rcosfir: T must be greater than zero') +end + +if (~strcmpi(filterType,{'normal','sqrt'})) + error('rcosfir: filter type must be ''normal'' or ''sqrt''') +end + +N = (nT(2)-nT(1))*rate+1; + +if (mod(N,2) == 0) + error('rcosfir: filter order (nT(2)-nT(1))*rate + 1 must be odd') +end + +n = (-(N-1)/2):((N-1)/2); + +n = n/(rate); + +if strcmpi(filterType,'normal') + % Raised cosine + h = sinc(n).*cos(pi*R*n)./(1-(2*R*n).^2); + id = rate*T/(2*R); + if (abs(fix(id) - id) < eps) + h(0.5*(N+1)+id) = sinc(1/(2*R))*pi/4; + h(0.5*(N+1)-id) = h(0.5*(N+1)+id); + end +else + % Root raised cosine + h = (sin(pi*n*(1-R)) + 4*R*n.*cos(pi*n*(1+R)))./(pi*n.*(1-(4*R*n).^2))/T; + + % Singularity h(0) + h(abs(n) < eps) = (1-R+4*R/pi)/T; + + % Singularities h(-rate*T/(4*R)) and h(rate*T/(4*R)) + id = rate*T/(4*R); + if (abs(round(id) - id) < eps) + h(0.5*(N+1)+id) = R*((1+2/pi)*sin(pi/(4*R))+(1-2/pi)*cos(pi/(4*R)))/(sqrt(2)*T); + h(0.5*(N+1)-id) = h(0.5*(N+1)+id); + end + % Normalize by the energy + h = h/sqrt(h*h'); +end + +% Normalize +%h = h/max(h); + +if (nargout == 2) + st = n/T; + st = st(2)-st(1); +end + +end + +%!test +%! [h, st] = rcosfir (0.2,[-3 3],4,1,'sqrt'); +%! assert (h, [-0.0189 0.0106 0.0424 0.0520 0.0233 -0.0360 -0.0924 -0.1000 -0.0263 0.1261 0.3136 0.4677 0.5273 0.4677 0.3136 0.1261 -0.0263 -0.1000 -0.0924 -0.0360 0.0233 0.0520 0.0424 0.0106 -0.0189], 2E-3) #checked against Matlab -- not clear why the discrepancy is so large +%! assert (st, 0.25) + +%!test +%! [h, st] = rcosfir (0.2,[-2 2],5,1,'sqrt'); +%! assert (h, [0.0208 -0.0206 -0.0654 -0.0927 -0.0825 -0.0235 0.0813 0.2134 0.3427 0.4371 0.4717 0.4371 0.3427 0.2134 0.0813 -0.0235 -0.0825 -0.0927 -0.0654 -0.0206 0.0208], 4E-3) +%! assert (st, 0.2, eps) + +%!test +%! [h, st] = rcosfir (0.2,[-3 3],4,1,'normal'); +%! assert (h, [2.7377e-17 6.0970e-02 1.0000e-01 8.2363e-02 -3.3461e-17 -1.1449e-01 -1.9489e-01 -1.6977e-01 3.7544e-17 2.9384e-01 6.3069e-01 8.9821e-01 1.0000e+00 8.9821e-01 6.3069e-01 2.9384e-01 3.7544e-17 -1.6977e-01 -1.9489e-01 -1.1449e-01 -3.3461e-17 8.2363e-02 1.0000e-01 6.0970e-02 2.7377e-17], 1E-5) +%! assert (st, 0.25) + diff --git a/inst/reedmullerdec.m b/inst/reedmullerdec.m new file mode 100644 index 0000000..ba41cff --- /dev/null +++ b/inst/reedmullerdec.m @@ -0,0 +1,266 @@ +## Copyright (C) 2007, 2011 Muthiah Annamalai +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} reedmullerdec (@var{VV}, @var{G}, @var{R}, @var{M}) +## +## Decode the received code word @var{VV} using the RM-generator matrix @var{G}, +## of order @var{R}, @var{M}, returning the code-word C. We use the standard +## majority logic vote method due to Irving S. Reed. The received word has to be +## a matrix of column size equal to to code-word size (i.e @math{2^m}). Each row +## is treated as a separate received word. +## +## The second return value is the message @var{M} got from @var{C}. +## +## G is obtained from definition type construction of Reed-Muller code, +## of order @var{R}, length @math{2^M}. Use the function reedmullergen, +## for the generator matrix for the (@var{R},@var{M}) order RM code. +## +## Faster code constructions (also easier) exist, but since +## finding permutation order of the basis vectors, is important, we +## stick with the standard definitions. To use decoder +## function reedmullerdec, you need to use this specific +## generator function. +## +## see: Lin & Costello, Ch.4, "Error Control Coding", 2nd Ed, Pearson. +## +## @example +## @group +## g = reedmullergen (2, 4); +## msg = rand (1, 11) > 0.5; +## c = mod (msg * g, 2); +## [dec_c, dec_m] = reedmullerdec (c, g, 2, 4) +## @end group +## @end example +## @seealso{reedmullergen, reedmullerenc} +## @end deftypefn + +## FIXME: make possible to use different generators, if permutation +## matrix (i.e polynomial vector elements of rows of G are given + +function [C, CMM] = reedmullerdec (VV, G, R, M) + + if (nargin != 4) + print_usage (); + endif + + ## we do a R+1 level majority logic decoding. + ## at each order of polynomial modifying the code-word. + U = 0:M-1; # allowed basis vectors in V2^M. + C = -1 * ones (size (VV)); # preset the output word. + [Rows, Cols] = size (G); # rows shadows rows() + + ## first get the row index of G & its corresponding permutation + ## elements. + P{1} = [0]; + for idx = 1:M + P{idx+1} = idx; + endfor + idx = idx + 1; + + Ufull = 1:M; + r = 2; + while (r <= R) + TMP = nchoosek (Ufull, r); + for idy = 1:nchoosek (M, r) + P{idx+idy} = TMP(idy,:); + endfor + idx = idx+idy; + r = r + 1; + endwhile + + ## enter majority logic decoding loop, R+1 order polynomial, + ## but we do it here for n-k times, both are equivalent. + + NCODES = size (VV); + NCODES = NCODES(1); + v_adjust = []; + + for row_v = 1:1:NCODES + V = VV(row_v,:); + CM = -1*ones (1, Rows); + + ## Now start at bottom row, and get the index set, + ## for each until the 2nd most row. + + ## special case, r=0, parity check, so just sum-up. + if (R == 0) + wt = __majority_logic_vote (V); + CMM(row_v,:) = wt; + C(row_v,:) = mod (wt*G, 2); + continue; + endif + + order = R; + Gadj = G; + prev_len = length (P{Rows}); + for idx = Rows:-1:1 + ## adjust the V received vector, at change of each order. + if (prev_len != length (P{idx}) || idx == 1) # force for_ idx=1 + v_adjust = mod (CM(idx+1:end)*Gadj(idx+1:end,:), 2); + Gadj(idx+1:end,:) = 0; + V = mod (V+ v_adjust, 2); # + = - in GF(2). + order = order - 1; + if (order == 0) # special handling of the all-1s basis vector. + CM(idx) = __majority_logic_vote (V); + break + endif + endif + + prev_len = length (P{idx}); + Si = P{idx}; # index identifier + Si = sort (Si, "descend"); + + ## generate index elements + B = __binvec (0:(2.^length (Si) - 1)); + WTS = 2.^[Si-1]; + ## actual index set elements. + S = sum (B.*repmat (WTS, [2^length(Si), 1]), 2); + + ## doing the operation set difference U \ S to get SCi + SCi = U; + Si_diff = Si-1; + rmidx = []; + for idy = 1:M + if (any (Si_diff == SCi(idy))) + rmidx = [rmidx, idy]; + endif + endfor + SCi(rmidx) = []; + SCi = sort (SCi, "descend"); + + ## corner case RM(r=m,m) case + if (length (SCi) > 0) + ## generate the set SC, + B = __binvec (0:(2.^length (SCi) - 1)); + WTS = 2.^[SCi]; + ## actual index set elements. + SC = sum (B.*repmat (WTS, [2^length(SCi), 1]), 2); + else + SC = [0]; # default, has to be empty set mathematically; + endif + + ## next compute the checksums & form the weights. + wts = []; # clear prev history + for id_el = 1:length (SC) + sc_el = SC(id_el); + elems = sc_el + S; + elems = elems + 1; # adjust indexing + wt = mod (sum (V(elems)), 2); # add elements of V, rx vector. + wts(id_el) = wt; # this is checksum + endfor + + ## do the majority logic vote. + CM(idx) = __majority_logic_vote (wts); + endfor + + CMM(row_v,:) = CM; + C(row_v,:) = mod (CM*G, 2); + endfor + +endfunction + +## +## utility functions +## + +function bvec = __binvec (dec_vec) + + maxlen = ceil (log2 (max (dec_vec) + 1)); + x = []; bvec = zeros (length (dec_vec), maxlen); + for idx = maxlen:-1:1 + tmp = mod (dec_vec, 2); + bvec(:,idx) = tmp.'; + dec_vec = (dec_vec - tmp) ./ 2; + endfor + +endfunction + +## +## crude majority logic decoding; force the = case to 0 by default. +## + +function wt = __majority_logic_vote (wts) + + wt = sum (wts) - sum (1 - wts); # count no of 1s - no of 0s. + if (wt != 0) + wt = (wt > 0); + #else + #wt = rand () > 0.5; # break the tie. + #endif + endif + +endfunction + +## +## majority logic decoding, tie-break using random. +## + +function wt = __majority_logic_vote_random (wts) + + wt = (1 + sign (sum (wts) - sum (1 - wts)))/2; + if (wt == 0.5) + wt = (rand () > 0.5); + endif + +endfunction + +% test cases +%G=[1 1 1 1,1 1 1 1; +% 0 1 0 1,0 1 0 1; +% 0 0 1 1,0 0 1 1; +% 0 0 0 0 1 1 1 1]; +%m=[1 0 0 1]; +%c=mod(m*G,2); +%c(1)=1-c(1); # corrects errors! +%[dc,dm]=reedmullerdec(c,G,1,3) +%pause +% +%G=reedmullergen(1,4); +%m=[1 0 0 0 1]; +%c=mod(m*G,2); +%[dc,dm]=reedmullerdec(c,G,1,4) +%pause +% +%G=reedmullergen(3,4); +%m=[ones(1,15)]; +%c=mod(m*G,2); +%[dc,dm]=reedmullerdec(c,G,3,4) +%pause +% +%G=reedmullergen(2,3); +%m=[0 0 0 1 1 1 1] +%c=mod(m*G,2) +%[dc,dm]=reedmullerdec(c,G,2,3) +%pause +% +%G=reedmullergen(3,3); +%c1=mod([ones(1,8)]*G,2); +%c2=mod([ones(1,4),zeros(1,4)]*G,2); +%[dC,dM]=reedmullerdec([c2;c2;c1;c2],G,3,3) +% +% ## special case of repetition code. +% G=reedmullergen(0,3); +% G +% c1=1*G; +% c2=0*G; C=[c1; c2] +% [dC,dM]=reedmullerdec(C,G,0,3) + +%% Test input validation +%!error reedmullerdec () +%!error reedmullerdec (1) +%!error reedmullerdec (1, 2) +%!error reedmullerdec (1, 2, 3) +%!error reedmullerdec (1, 2, 3, 4, 5) diff --git a/inst/reedmullerenc.m b/inst/reedmullerenc.m new file mode 100644 index 0000000..ac1d05f --- /dev/null +++ b/inst/reedmullerenc.m @@ -0,0 +1,58 @@ +## Copyright (C) 2007 Muthiah Annamalai +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} reedmullerenc (@var{MSG}, @var{R}, @var{M}) +## +## Definition type construction of Reed-Muller code, +## of order @var{R}, length @math{2^M}. This function +## returns the generator matrix for the said order RM code. +## +## Encodes the given message word/block, of column size k, +## corresponding to the RM(@var{R},@var{M}), and outputs a +## code matrix @var{C}, on each row with corresponding codeword. +## The second return value is the @var{G}, which is generator matrix +## used for this code. +## +## @example +## @group +## msg = rand (10, 11) > 0.5; +## [c, g] = reedmullerenc (msg, 2, 4); +## @end group +## @end example +## @seealso{reedmullerdec, reedmullergen} +## @end deftypefn + +function [C, G] = reedmullerenc (MSG, R, M) + + if (nargin != 3) + print_usage (); + endif + G = reedmullergen (R, M); + if (columns (MSG) != rows (G)) + error ("reedmullerenc: MSG must be a matrix with K columns"); + endif + C = zeros (rows (MSG), 2.^M); + for idx = 1:rows (MSG) + C(idx,:) = mod (MSG(idx,:)*G, 2); + endfor + +endfunction + +%% Test input validation +%!error reedmullerenc () +%!error reedmullerenc (1) +%!error reedmullerenc (1, 2) +%!error reedmullerenc (1, 2, 3, 4) diff --git a/inst/reedmullergen.m b/inst/reedmullergen.m new file mode 100644 index 0000000..7152392 --- /dev/null +++ b/inst/reedmullergen.m @@ -0,0 +1,87 @@ +## Copyright (C) 2007 Muthiah Annamalai +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} reedmullergen (@var{R}, @var{M}) +## +## Definition type construction of Reed-Muller code, +## of order @var{R}, length @math{2^M}. This function +## returns the generator matrix for the said order RM code. +## +## RM(r,m) codes are characterized by codewords, +## @code{sum ( (m,0) + (m,1) + @dots{} + (m,r)}. +## Each of the codeword is got through spanning the +## space, using the finite set of m-basis codewords. +## Each codeword is @math{2^M} elements long. +## see: Lin & Costello, "Error Control Coding", 2nd Ed. +## +## Faster code constructions (also easier) exist, but since +## finding permutation order of the basis vectors, is important, we +## stick with the standard definitions. To use decoder +## function reedmullerdec, you need to use this specific +## generator function. +## +## @example +## @group +## g = reedmullergen (2, 4); +## @end group +## @end example +## @seealso{reedmullerdec, reedmullerenc} +## @end deftypefn + +function G = reedmullergen (R, M) + + if (nargin != 2) + print_usage (); + endif + + G = ones (1, 2^M); + if (R == 0) + return; + endif + + a = [0]; + b = [1]; + V = []; + for idx = 1:M; + row = repmat ([a, b], [1, 2^(M-idx)]); + V(idx,:) = row; + a = [a, a]; + b = [b, b]; + endfor + + G = [G; V]; + + if (R == 1) + return + else + r = 2; + while (r <= R) + p = nchoosek (1:M, r); + prod = V(p(:,1),:) .* V(p(:,2),:); + for idx = 3:r + prod = prod .* V(p(:,idx),:); + endfor + G = [G; prod]; + r = r + 1; + endwhile + endif + +endfunction + +%% Test input validation +%!error reedmullergen () +%!error reedmullergen (1) +%!error reedmullergen (1, 2, 3) diff --git a/inst/ricedeco.m b/inst/ricedeco.m new file mode 100644 index 0000000..443f546 --- /dev/null +++ b/inst/ricedeco.m @@ -0,0 +1,86 @@ +## Copyright (C) 2006 Muthiah Annamalai +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} ricedeco (@var{code}, @var{K}) +## +## Returns the Rice decoded signal vector using @var{code} and @var{K}. +## Compulsory K is need to be specified. +## A restrictions is that a signal set must strictly be non-negative. +## The value of code is a cell array of row-vectors which have the +## encoded rice value for a single sample. The Rice algorithm is +## used to encode the "code" and only that can be meaningfully +## decoded. @var{code} is assumed to have been of format generated +## by the function @code{riceenco}. +## +## Reference: Solomon Golomb, Run length Encodings, 1966 IEEE Trans Info Theory +## +## An example of the use of @code{ricedeco} is +## @example +## @group +## ricedeco (riceenco (1:4, 2), 2) +## @result{} [1 2 3 4] +## @end group +## @end example +## @seealso{riceenco} +## @end deftypefn + +## +## +##! /usr/bin/octave -q +##A stress test routine +##for i=1:100 +## sig=abs(randint(1,10,[0,255])); +## [code,k]=riceenco(sig) +## sig_d=ricedeco(code,k) +## if(isequal(sig_d,sig)!=1) +## error("Some mistake in ricedeco/enco pair"); +## endif +##endfor +## + +function sig_op = ricedeco (code, K) + + if (nargin != 2 || ! iscell (code)) + print_usage (); + endif + + L = length (code); + + K_pow_2 = 2**K; + + if (K != 0) + power_seq = [2.^((K-1):-1:0)]; + for j = 1:L + word = code{j}; + idx = find (word == 0)(1); + val = sum (word(1:idx)); + sig_op(j) = val * K_pow_2 + sum (word(idx+1:end) .* power_seq); + endfor + else + for j = 1:L + sig_op(j) = sum (code{j}); + endfor + endif + +endfunction + +%!assert (ricedeco (riceenco (1:4, 2), 2), [1:4]) + +%% Test input validation +%!error ricedeco () +%!error ricedeco (1) +%!error ricedeco (1, 2) +%!error ricedeco (1, 2, 3) diff --git a/inst/riceenco.m b/inst/riceenco.m new file mode 100644 index 0000000..ca448db --- /dev/null +++ b/inst/riceenco.m @@ -0,0 +1,115 @@ +## Copyright (C) 2006 Muthiah Annamalai +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} riceenco (@var{sig}, @var{K}) +## +## Returns the Rice encoded signal using @var{K} or optimal K . +## Default optimal K is chosen between 0-7. Currently no other way +## to increase the range except to specify explicitly. Also returns +## @var{K} parameter used (in case it were to be chosen optimally) +## and @var{Ltot} the total length of output code in bits. +## This function uses a @var{K} if supplied or by default chooses +## the optimal K for encoding signal vector into a rice coded vector. +## A restrictions is that a signal set must strictly be non-negative. +## The Rice algorithm is used to encode the data into unary coded +## quotient part which is represented as a set of 1's separated from +## the K-part (binary) using a zero. This scheme doesn't need any +## kind of dictionaries and its close to O(N), but this implementation +## *may be* sluggish, though correct. +## +## Reference: Solomon Golomb, Run length Encodings, 1966 IEEE Trans +## Info' Theory +## +## An example of the use of @code{riceenco} is +## @example +## @group +## riceenco (1:4) +## @result{} @{[0 1], [1 0 0], [1 0 1], [1 1 0 0]@} +## riceenco (1:10, 2) +## @result{} @{[0 0 1], [0 1 0], [0 1 1], [1 0 0 0], +## [1 0 0 1], [1 0 1 0], [1 0 1 1], [1 1 0 0 0], +## [1 1 0 0 1], [1 1 0 1 0]@} +## @end group +## @end example +## @seealso{ricedeco} +## @end deftypefn + +function [rcode, K, Ltot] = riceenco (sig, K) + + if (nargin < 1 || nargin > 2) + print_usage (); + elseif (nargin < 2) + use_optimal_k = 1; + else + use_optimal_k = 0; + endif + + if (min (sig) < 0) + error ("riceenco: all elements of SIG must be non-negative numbers"); + endif + + + L = length (sig); + + ## compute the optimal rice parameter. + if (use_optimal_k) + k_opt = 0; + len_past = sum (sig) + L + k_opt*L; + quot = sig; + + for k = 1:7 + k_pow_2 = 2**k; + quot_k = floor (sig./k_pow_2); + len = sum (quot_k)+L+k*L; + if (len < len_past) + len_past = len; + k_opt = k; + rem = mod (sig, k_pow_2); + quot = quot_k; + endif + endfor + Ltot = len_past; + K = k_opt; + K_pow_2 = 2**K; + else + K_pow_2 = 2**K; + quot = floor (sig./K_pow_2); + rem = mod (sig, K_pow_2); + endif + + for j = 1:L + rice_part = zeros (1, K); + ## + ## How can we eliminate this loop? + ## I essentially need to get the binary + ## representation of rem(j) in the rice_part(i) + ## + for i = K:-1:1 + rice_part(i) = mod (rem(j), 2); + rem(j) = floor (rem(j)/2); + endfor + rcode{j} = [ones(1, quot(j)) 0 rice_part]; + endfor + Ltot = sum (quot) + L + K*L; + +endfunction + +%!assert (riceenco (1:4, 2), {[0 0 1], [0 1 0], [0 1 1], [1 0 0 0]}) + +%% Test input validation +%!error riceenco () +%!error riceenco (1, 2, 3) +%!error riceenco (-1) diff --git a/inst/rledeco.m b/inst/rledeco.m new file mode 100644 index 0000000..caab8bc --- /dev/null +++ b/inst/rledeco.m @@ -0,0 +1,55 @@ +## Copyright (C) 2006 Muthiah Annamalai +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} rledeco (@var{message}) +## +## Returns decoded run-length @var{message}. The RLE encoded @var{message} +## has to be in the form of a row-vector. The message format (encoded RLE) +## is like repetition [factor, value]+. +## +## An example use of @code{rledeco} is +## @example +## @group +## message = [1 5 2 4 3 1]; +## rledeco (message) +## @result{} [5 4 4 1 1 1] +## @end group +## @end example +## @seealso{rledeco} +## @end deftypefn + +function rmsg = rledeco (message) + + if (nargin != 1) + print_usage (); + endif + rmsg = []; + L = length (message); + itr = 1; + while (itr < L) + times = message(itr); + val = message(itr+1); + rmsg = [rmsg val * (ones (1, times))]; + itr = itr + 2; + endwhile + +endfunction + +%!assert (rledeco ([1 5 2 4 3 1]), [5 4 4 1 1 1]) + +%% Test input validation +%!error rledeco () +%!error rledeco (1, 2) diff --git a/inst/rleenco.m b/inst/rleenco.m new file mode 100644 index 0000000..5df52fd --- /dev/null +++ b/inst/rleenco.m @@ -0,0 +1,59 @@ +## Copyright (C) 2006 Muthiah Annamalai +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} rleenco (@var{message}) +## +## Returns run-length encoded @var{message}. The RLE form is built from +## @var{message}. The original @var{message} has to be in the form of a +## row-vector. The encoded @var{message} format (encoded RLE) is like +## [repetition factor]+, values. +## +## An example use of @code{rleenco} is +## @example +## @group +## message = [5 4 4 1 1 1] +## rleenco (message) +## @result{} [1 5 2 4 3 1]; +## @end group +## @end example +## @seealso{rleenco} +## @end deftypefn + +function rmsg = rleenco (message) + + if (nargin != 1) + print_usage (); + endif + rmsg = []; + L = length (message); + itr = 1; + while (itr <= L) + times = 0; + val = message(itr); + while (itr <= L && message(itr) == val) + itr = itr + 1; + times = times + 1; + endwhile + rmsg = [rmsg times val]; + endwhile + +endfunction + +%!assert (rleenco ([5 4 4 1 1 1]), [1 5 2 4 3 1]) + +%% Test input validation +%!error rleenco () +%!error rleenco (1, 2) diff --git a/inst/rsdecof.m b/inst/rsdecof.m new file mode 100644 index 0000000..5c2458c --- /dev/null +++ b/inst/rsdecof.m @@ -0,0 +1,99 @@ +## Copyright (C) 2003 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} rsdecof (@var{in}, @var{out}) +## @deftypefnx {Function File} {} rsdecof (@var{in}, @var{out}, @var{t}) +## +## Decodes an ASCII file using a Reed-Solomon coder. The input file is +## defined by @var{in} and the result is written to the output file @var{out}. +## The type of coding to use is determined by whether the input file is 7- +## or 8-bit. If the input file is 7-bit, the default coding is [127,117]. +## while the default coding for an 8-bit file is a [255, 235]. This allows +## for 5 or 10 error characters in 127 or 255 symbols to be corrected +## respectively. The number of errors that can be corrected can be overridden +## by the variable @var{t}. +## +## If the file is not an integer multiple of the message size (127 or 255) +## in length, then the file is padded with the EOT (ASCII character 4) +## character before decoding. +## +## @seealso{rsencof} +## @end deftypefn + +function rsdecof (in, out, t) + + if (nargin < 2 || nargin > 3) + print_usage (); + endif + + if (!ischar (in) || !ischar (out)) + error ("rsdecof: IN and OUT must be strings"); + endif + + if (nargin != 3) + t = 0; + else + if (! (isscalar (t) && t == fix (t) && t > 0)) + error ("rsdecof: T must be a positive integer"); + endif + endif + + try fid = fopen (in, "rt"); + catch + error ("rsdecof: could not open '%s' for reading", in); + end_try_catch + [code, count] = fread (fid, Inf, "char"); + fclose (fid); + + is8bit = (max (code) > 127); + + if (is8bit) + m = 8; + n = 255; + if (t == 0) + t = 10; + endif + else + m = 7; + n = 127; + if (t == 0) + t = 5; + endif + endif + k = n - 2 * t; + + ncodewords = ceil (count / n); + npad = n * ncodewords - count; + code = reshape ([code ; 4 * ones(npad, 1)], n, ncodewords)'; + + msg = rsdec (gf (code, m), n, k, "beginning")'; + msg = msg(:); + + try fid = fopen (out, "w+t"); + catch + error ("rsdecof: could not open '%s' for writing", out); + end_try_catch + fwrite (fid, msg(1:(ncodewords*k-npad)), "char"); + fclose (fid); + +endfunction + +%% Test input validation +%!error rsdecof () +%!error rsdecof (1) +%!error rsdecof (1, 2, 3, 4) +%!error rsdecof (1, 2) +%!error rsdecof ("in", "out", 0) diff --git a/inst/rsencof.m b/inst/rsencof.m new file mode 100644 index 0000000..f6844bd --- /dev/null +++ b/inst/rsencof.m @@ -0,0 +1,119 @@ +## Copyright (C) 2003 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} rsencof (@var{in}, @var{out}) +## @deftypefnx {Function File} {} rsencof (@var{in}, @var{out}, @var{t}) +## @deftypefnx {Function File} {} rsencof (@dots{}, @var{pad}) +## +## Encodes an ASCII file using a Reed-Solomon coder. The input file is +## defined by @var{in} and the result is written to the output file @var{out}. +## The type of coding to use is determined by whether the input file is 7- +## or 8-bit. If the input file is 7-bit, the default coding is [127,117]. +## while the default coding for an 8-bit file is a [255, 235]. This allows +## for 5 or 10 error characters in 127 or 255 symbols to be corrected +## respectively. The number of errors that can be corrected can be overridden +## by the variable @var{t}. +## +## If the file is not an integer multiple of the message size (127 or 255) +## in length, then the file is padded with the EOT (ASCII character 4) +## characters before coding. Whether these characters are written to the +## output is defined by the @var{pad} variable. Valid values for @var{pad} +## are "pad" (the default) and "nopad", which write or not the padding +## respectively. +## +## @seealso{rsdecof} +## @end deftypefn + +function rsencof (in, out, varargin) + + if (nargin < 2 || nargin > 4) + print_usage (); + endif + + if (!ischar (in) || !ischar (out)) + error ("rsencof: IN and OUT must be strings"); + endif + + t = 0; + pad = 1; + for i = 1:length (varargin) + arg = varargin{i}; + if (ischar (arg)) + if (strcmp (arg, "pad")) + pad = 1; + elseif (strcmp (arg, "nopad")) + pad = 0; + else + error ("rsencof: unrecognized string argument"); + endif + else + if (! (isscalar (t) && t == fix (d) && t > 0)) + error ("rsencof: T must be a positive integer"); + endif + endif + endfor + + try fid = fopen (in, "r"); + catch + error ("rsencof: could not open '%s' for reading", in); + end_try_catch + [msg, count] = fread (fid, Inf, "char"); + fclose (fid); + + is8bit = (max (msg) > 127); + + if (is8bit) + m = 8; + n = 255; + if (t == 0) + t = 10; + endif + else + m = 7; + n = 127; + if (t == 0) + t = 5; + endif + endif + k = n - 2 * t; + + ncodewords = ceil (count / k); + npad = k * ncodewords - count; + msg = reshape ([msg ; 4 * ones(npad, 1)], k, ncodewords)'; + + code = rsenc (gf (msg, m), n, k, "beginning")'; + code = code(:); + + try fid = fopen (out, "w"); + catch + error ("rsencof: could not open '%s' for writing", out); + end_try_catch + if (pad) + fwrite (fid, code, "char"); + else + fwrite (fid, code(1:(ncodewords*n-npad)), "char"); + endif + fclose (fid); + +endfunction + +%% Test input validation +%!error rsencof () +%!error rsencof (1) +%!error rsencof (1, 2, 3, 4, 5) +%!error rsencof (1, 2) +%!error rsencof ("in", "out", 0) +%!error rsencof ("in", "out", "invalid") diff --git a/inst/rsgenpoly.m b/inst/rsgenpoly.m new file mode 100644 index 0000000..6cc01bb --- /dev/null +++ b/inst/rsgenpoly.m @@ -0,0 +1,155 @@ +## Copyright (C) 2003 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{g} =} rsgenpoly (@var{n}, @var{k}) +## @deftypefnx {Function File} {@var{g} =} rsgenpoly (@var{n}, @var{k}, @var{p}) +## @deftypefnx {Function File} {@var{g} =} rsgenpoly (@var{n}, @var{k}, @var{p}, @var{b}, @var{s}) +## @deftypefnx {Function File} {@var{g} =} rsgenpoly (@var{n}, @var{k}, @var{p}, @var{b}) +## @deftypefnx {Function File} {[@var{g}, @var{t}] =} rsgenpoly (@dots{}) +## +## Creates a generator polynomial for a Reed-Solomon coding with message +## length of @var{k} and codelength of @var{n}. @var{n} must be greater +## than @var{k} and their difference must be even. The generator polynomial +## is returned on @var{g} as a polynomial over the Galois Field GF(2^@var{m}) +## where @var{n} is equal to @code{2^@var{m}-1}. If @var{m} is not integer +## the next highest integer value is used and a generator for a shorten +## Reed-Solomon code is returned. +## +## The elements of @var{g} represent the coefficients of the polynomial in +## descending order. If the length of @var{g} is lg, then the generator +## polynomial is given by +## @tex +## $$ +## g_0 x^{lg-1} + g_1 x^{lg-2} + \cdots + g_{lg-1} x + g_lg. +## $$ +## @end tex +## @ifnottex +## +## @example +## @var{g}(0) * x^(lg-1) + @var{g}(1) * x^(lg-2) + ... + @var{g}(lg-1) * x + @var{g}(lg). +## @end example +## @end ifnottex +## +## If @var{p} is defined then it is used as the primitive polynomial of the +## Galois Field GF(2^@var{m}). The default primitive polynomial will be used +## if @var{p} is equal to []. +## +## The variables @var{b} and @var{s} determine the form of the generator +## polynomial in the following manner. +## @tex +## $$ +## g = (x - A^{bs}) (x - A^{(b+1)s}) \cdots (x - A ^{(b+2t-1)s}). +## $$ +## @end tex +## @ifnottex +## +## @example +## @var{g} = (@var{x} - A^(@var{b}*@var{s})) * (@var{x} - A^((@var{b}+1)*@var{s})) * ... * (@var{x} - A^((@var{b}+2*@var{t}-1)*@var{s})). +## @end example +## @end ifnottex +## +## where @var{t} is @code{(@var{n}-@var{k})/2}, and A is the primitive element +## of the Galois Field. Therefore @var{b} is the first consecutive root of the +## generator polynomial and @var{s} is the primitive element to generate the +## polynomial roots. +## +## If requested the variable @var{t}, which gives the error correction +## capability of the Reed-Solomon code. +## @seealso{gf, rsenc, rsdec} +## @end deftypefn + +function [g, t] = rsgenpoly (n, k, _prim, _b, _s) + + if (nargin < 2 || nargin > 5) + print_usage (); + endif + + if (! (isscalar (n) && n == fix (n) && n > 2)) + error ("rsgenpoly: N must be an integer greater than 2"); + endif + + if (! (isscalar (k) && k == fix (k) && k > 0)) + error ("rsgenpoly: K must be a non-negative integer"); + endif + + if ((n-k)/2 != fix ((n-k)/2)) + error ("rsgenpoly: N-K must be an even integer"); + endif + + m = ceil (log2 (n+1)); + ## Adjust n and k if n not equal to 2^m-1 + dif = 2^m - 1 - n; + n = n + dif; + k = k + dif; + + prim = 0; + if (nargin > 2) + if (isempty (_prim)) + prim = 0; + else + prim = _prim; + endif + endif + + if (! (isscalar (prim) && prim == fix (prim) && prim >= 0)) + error ("rsgenpoly: P must be an integer representing a primitive polynomial"); + endif + + if (prim != 0) + if (!isprimitive (prim)) + error ("rsgenpoly: P must be an integer representing a primitive polynomial"); + endif + + if (prim < 2^m || prim > 2^(m+1)) + error ("rsgenpoly: P must be a primitive polynomial with order 2^M"); + endif + endif + + b = 1; + if (nargin > 3) + b = _b; + endif + + if (! (isscalar (b) && b == fix (b) && b >= 0)) + error ("rsgenpoly: B must be a non-negative integer"); + endif + + s = 1; + if (nargin > 4) + s = _s; + endif + + if (! (isscalar (s) && s == fix (s) && s >= 0)) + error ("rsgenpoly: S must be a non-negative integer"); + endif + + alph = gf (2, m, prim); + t = (n - k) / 2; + + g = gf (1, m, prim); + for i = 1:2*t + g = conv (g, gf ([1, alph^((b+i-1)*s)], m, prim)); + endfor + +endfunction + +%% Test input validation +%!error rsgenpoly () +%!error rsgenpoly (1) +%!error rsgenpoly (1, 2, 3, 4, 5, 6) +%!error rsgenpoly (1, 2) +%!error rsgenpoly (2, 0) +%!error rsgenpoly (4, 3) diff --git a/inst/scatterplot.m b/inst/scatterplot.m new file mode 100644 index 0000000..9c603e3 --- /dev/null +++ b/inst/scatterplot.m @@ -0,0 +1,168 @@ +## Copyright (C) 2003 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} scatterplot (@var{x}) +## @deftypefnx {Function File} {} scatterplot (@var{x}, @var{n}) +## @deftypefnx {Function File} {} scatterplot (@var{x}, @var{n}, @var{off}) +## @deftypefnx {Function File} {} scatterplot (@var{x}, @var{n}, @var{off}, @var{str}) +## @deftypefnx {Function File} {} scatterplot (@var{x}, @var{n}, @var{off}, @var{str}, @var{h}) +## @deftypefnx {Function File} {@var{h} =} scatterplot (@dots{}) +## +## Display the scatter plot of a signal. The signal @var{x} can be either in +## one of three forms +## +## @table @asis +## @item A real vector +## In this case the signal is assumed to be real and represented by the vector +## @var{x}. The scatterplot is plotted along the x axis only. +## @item A complex vector +## In this case the in-phase and quadrature components of the signal are +## plotted separately on the x and y axes respectively. +## @item A matrix with two columns +## In this case the first column represents the in-phase and the second the +## quadrature components of a complex signal and are plotted on the x and +## y axes respectively. +## @end table +## +## Each point of the scatter plot is assumed to be separated by @var{n} +## elements in the signal. The first element of the signal to plot is +## determined by @var{off}. By default @var{n} is 1 and @var{off} is 0. +## +## The string @var{str} is a plot style string (example "r+"), +## and by default is the default gnuplot point style. +## +## The figure handle to use can be defined by @var{h}. If @var{h} is not +## given, then the next available figure handle is used. The figure handle +## used in returned on @var{hout}. +## @seealso{eyediagram} +## @end deftypefn + +function varargout = scatterplot (x, n, _off, str, h) + + if (nargin < 1 || nargin > 5) + print_usage (); + endif + + if (isreal (x)) + if (min (size (x)) == 1) + signal = "real"; + xr = x(:); + xi = zeros (size (xr)); + elseif (size (x, 2) == 2) + signal = "complex"; + xr = x(:,1); + xi = x(:,2); + else + error ("scatterplot: real X must be a vector or a 2-column matrix"); + endif + else + signal = "complex"; + if (min (size (x)) != 1) + error ("scatterplot: complex X must be a vector"); + endif + xr = real (x(:)); + xi = imag (x(:)); + endif + + if (!length (xr)) + error ("scatterplot: X must not be empty"); + endif + + if (nargin > 1) + if (! (isscalar (n) && isreal (n) && n == fix (n) && n > 0)) + error ("scatterplot: N must be a positive integer"); + endif + else + n = 1; + endif + + if (nargin > 2) + if (! (isscalar (_off) && isreal (_off) && _off == fix (_off) + && _off >= 0 && _off < length (x))) + error ("scatterplot: OFF must be an integer in the range [0,N-1]"); + endif + off = _off; + else + off = 0; + endif + + if (nargin > 3) + if (isempty (str)) + fmt = "."; + elseif (ischar (str)) + fmt = str; + else + error ("scatterplot: STR must be a string"); + endif + else + fmt = "."; + endif + + if (nargin > 4) + if (isempty (h)) + hout = figure (); + elseif (isfigure (h) && strcmp (get (h, "tag"), "scatterplot")) + hout = h; + else + error ("scatterplot: H must be a scatterplot figure handle"); + endif + else + hout = figure (); + endif + set (hout, "tag", "scatterplot"); + set (hout, "name", "Scatter Plot"); + set (0, "currentfigure", hout); + + xr = xr(off+1:n:rows (xr)); + xi = xi(off+1:n:rows (xi)); + + plot (xr, xi, fmt); + if (!strcmp (signal, "complex")) + ## FIXME: What is the appropriate xrange + xmax = max (xr); + xmin = min (xr); + xran = xmax - xmin + xmax = ceil (2 * xmax / xran) / 2 * xran; + xmin = floor (2 * xmin / xran) / 2 * xran; + axis ([xmin, xmax, -1, 1]); + endif + title ("Scatter plot"); + xlabel ("In-phase"); + ylabel ("Quadrature"); + legend ("off"); + + if (nargout > 0) + varargout{1} = hout; + endif + +endfunction + +%!demo +%! n = 200; +%! ovsp = 5; +%! x = 1:n; +%! xi = [1:1/ovsp:n-0.1]; +%! y = randsrc (1, n, [1 + i, 1 - i, -1 - i, -1 + i]); +%! yi = interp1 (x, y, xi); +%! noisy = awgn (yi, 15, "measured"); +%! h = scatterplot (noisy); +%! hold on; +%! scatterplot (noisy, ovsp, 0, "r+", h); + +%% Test input validation +%!error scatterplot () +%!error scatterplot (1, 2, 3, 4, 5, 6) +%!error scatterplot (1, -1) diff --git a/inst/shannonfanodeco.m b/inst/shannonfanodeco.m new file mode 100644 index 0000000..da3854e --- /dev/null +++ b/inst/shannonfanodeco.m @@ -0,0 +1,150 @@ +## Copyright (C) 2006 Muthiah Annamalai +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} shannonfanodeco (@var{hcode}, @var{dict}) +## +## Returns the original signal that was Shannon-Fano encoded. The signal +## was encoded using @code{shannonfanoenco}. This function uses +## a dict built from the @code{shannonfanodict} and uses it to decode a signal +## list into a Shannon-Fano list. Restrictions include hcode is expected to be a binary code; +## returned signal set that strictly belongs in the @code{range [1,N]}, +## with @code{N = length (dict)}. Also dict can only be from the +## @code{shannonfanodict (...)} routine. Whenever decoding fails, +## those signal values are indicated by -1, and we successively +## try to restart decoding from the next bit that hasn't failed in +## decoding, ad-infinitum. +## +## An example use of @code{shannonfanodeco} is +## @example +## @group +## hd = shannonfanodict (1:4, [0.5 0.25 0.15 0.10]); +## hcode = shannonfanoenco (1:4, hd) +## @result{} hcode = [0 1 0 1 1 0 1 1 1 0] +## shannonfanodeco (hcode, hd) +## @result{} [1 2 3 4] +## @end group +## @end example +## @seealso{shannonfanoenco, shannonfanodict} +## @end deftypefn + +function sig = shannonfanodeco (hcode, dict) + + if (nargin != 2 || ! iscell (dict)) + print_usage (); + endif + if (max (hcode) > 1 || min (hcode) < 0) + error ("shannonfanodeco: all elements of HCODE must be in the range [0,1]"); + endif + + ## FIXME: + ## O(log(N)) algorithms exist, but we need some effort to implement those + ## Maybe sometime later, it would be a nice 1-day project + ## Ref: A memory efficient Shannonfano Decoding Algorithm, AINA 2005, IEEE + ## + + ## FIXME: Somebody can implement a "faster" algorithm than O(N^3) at present + ## Decoding Algorithm O(N+k*log(N)) which is approximately O(N+Nlog(N)) + ## + ## 1. Separate the dictionary by the lengths + ## and knows symbol correspondence. + ## + ## 2. Find the symbol in the dict of lengths l,h where + ## l = smallest cw length ignoring 0 length CW, and + ## h = largest cw length , with k=h-l+1; + ## + ## 3. Match the k codewords to the dict using binary + ## search, and then you can declare decision. + ## + ## 4. In case of non-decodable words skip the start-bit + ## used in the previous case, and then restart the same + ## procedure from the next bit. + ## + L = length (dict); + lenL = length (dict{1}); + lenH = 0; + + ## + ## Know the ranges of operation + ## + for itr = 1:L + t = length (dict{itr}); + if (t < lenL) + lenL = t; + endif + if (t > lenH) + lenH = t; + endif + endfor + + ## + ## Now do a O(N^4) algorithm + ## + itr = 0; # offset into the hcode + sig = []; # output + CL = length (hcode); + + ## whole decoding loop. + while (itr < CL) + ## decode one element (or just try to). + for itr_y = lenL:lenH + ## look for word in dictionary. + ## with flag to indicate found + ## or not found. Detect end of buffer. + + if ((itr+itr_y) > CL) + break; + endif + + word = hcode(itr+1:itr+itr_y); + flag = 0; + + ## word + + ## search loop. + for itr_z = 1:L + if (isequal (dict{itr_z}, word)) + itr = itr + itr_y; + sig = [sig itr_z]; + flag = 1; + break; + endif + endfor + + if (flag == 1) + break; # also need to break_ above then. + endif + + endfor + + + ## could not decode + if (flag == 0) + itr = itr + 1; + sig = [sig -1]; + endif + + endwhile + +endfunction + +%!assert (shannonfanodeco (shannonfanoenco (1:4, shannonfanodict (1:4, [0.5 0.25 0.15 0.10])), shannonfanodict (1:4, [0.5 0.25 0.15 0.10])), [1:4], 0) + +%% Test input validation +%!error shannonfanodeco () +%!error shannonfanodeco (1) +%!error shannonfanodeco (1, 2, 3) +%!error shannonfanodeco (1, 2) +%!error shannonfanodeco (2, {}) diff --git a/inst/shannonfanodict.m b/inst/shannonfanodict.m new file mode 100644 index 0000000..214f798 --- /dev/null +++ b/inst/shannonfanodict.m @@ -0,0 +1,122 @@ +## Copyright (C) 2006 Muthiah Annamalai +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} shannonfanodict (@var{symbols}, @var{symbol_probabilites}) +## +## Returns the code dictionary for source using Shannon-Fano algorithm. +## Dictionary is built from @var{symbol_probabilities} using the +## Shannon-Fano scheme. Output is a dictionary cell-array, which +## are codewords, and correspond to the order of input probability. +## +## @example +## @group +## cw = shannonfanodict (1:4, [0.5 0.25 0.15 0.1]); +## assert (redundancy (cw, [0.5 0.25 0.15 0.1]), 0.25841, 0.001) +## shannonfanodict (1:5, [0.35 0.17 0.17 0.16 0.15]) +## shannonfanodict (1:8, [8 7 6 5 5 4 3 2] / 40) +## @end group +## @end example +## @seealso{shannonfanoenc, shannonfanodec} +## @end deftypefn + +function cw_list = shannonfanodict (symbol, P) + + if (nargin != 2) + print_usage (); + endif + + DMAX = length (P); + S = 1:DMAX; + + if (sum (P) - 1.000 > 1e-7) + error ("shannonfanodict: the elements of P must add up to 1"); + endif + ## + ## FIXME: Is there any other way of doing the + ## topological sort? Insertion sort is bad. + ## + ## Sort the probability list in + ## descending/non-increasing order. + ## Using plain vanilla insertion sort. + ## + for i = 1:DMAX + for j = i:DMAX + + if (P(i) < P(j)) + + ## Swap prob + t = P(i); + P(i) = P(j); + P(j) = t; + + ## Swap symb + t = S(i); + S(i) = S(j); + S(j) = t; + endif + + endfor + endfor + + + ## Now for each symbol you need to + ## create code as first [-log p(i)] bits of + ## cumulative function sum(p(1:i)) + ## + ## printf("Shannon Codes\n"); + ## data_table=zeros(1,DMAX); + cw_list = {}; + + for itr = 1:DMAX + if (P(itr) != 0) + digits = ceil (-log2 (P(itr))); # somany digits needed. + else + digits = 0; # dont assign digits for zero probability symbols. + endif + + Psum = sum ([0 P](1:itr)); # Cumulative probability + s = []; + for i = 1:digits; + Psum = 2 * Psum; + if (Psum >= 1.00) + s = [s 1]; + Psum = Psum - 1.00; + else + s = [s 0]; + endif + endfor + cw_list{itr} = s; + endfor + + ## re-arrange the list accroding to input prob list. + cw_list2 = {}; + for i = 1:length (cw_list) + cw_list2{i} = cw_list{S(i)}; + endfor + cw_list = cw_list2; + +endfunction + +%!shared CW, P +%!test +%! P = [0.5 0.25 0.15 0.1]; +%! assert (shannonfanodict (1:4, P), {[0], [1 0], [1 1 0], [1 1 1 0]}) + +%% Test input validation +%!error shannonfanodict () +%!error shannonfanodict (1) +%!error shannonfanodict (1, 2, 3) +%!error shannonfanodict (1, [0.5 0.5 0.5]) diff --git a/inst/shannonfanoenco.m b/inst/shannonfanoenco.m new file mode 100644 index 0000000..82c9942 --- /dev/null +++ b/inst/shannonfanoenco.m @@ -0,0 +1,55 @@ +## Copyright (C) 2006 Muthiah Annamalai +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} shannonfanoenco (@var{hcode}, @var{dict}) +## +## Returns the Shannon-Fano encoded signal using @var{dict}. +## This function uses a @var{dict} built from the @code{shannonfanodict} +## and uses it to encode a signal list into a Shannon-Fano code. +## Restrictions include a signal set that strictly belongs in the +## @code{range [1,N]} with @code{N = length (dict)}. Also dict can only be +## from the @code{shannonfanodict} routine. +## An example use of @code{shannonfanoenco} is +## +## @example +## @group +## hd = shannonfanodict (1:4, [0.5 0.25 0.15 0.10]); +## shannonfanoenco (1:4, hd) +## @result{} [0 1 0 1 1 0 1 1 1 0] +## @end group +## @end example +## @seealso{shannonfanodeco, shannonfanodict} +## @end deftypefn + +function sf_code = shannonfanoenco (sig, dict) + + if (nargin != 2) + print_usage (); + endif + if (max (sig) > length (dict) || min (sig) < 1) + error ("shannonfanoenco: all elements of SIG must be in the range [1,N]"); + endif + sf_code = [dict{sig}]; + +endfunction + +%!assert (shannonfanoenco (1:4, shannonfanodict (1:4, [0.5 0.25 0.15 0.10])), [0 1 0 1 1 0 1 1 1 0], 0) + +%% Test input validation +%!error shannonfanoenco () +%!error shannonfanoenco (1) +%!error shannonfanoenco (1, 2, 3) +%!error shannonfanoenco (1, {}) diff --git a/inst/symerr.m b/inst/symerr.m new file mode 100644 index 0000000..0d7c040 --- /dev/null +++ b/inst/symerr.m @@ -0,0 +1,149 @@ +## Copyright (C) 2003 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {[@var{num}, @var{rate}] =} symerr (@var{a}, @var{b}) +## @deftypefnx {Function File} {[@var{num}, @var{rate}] =} symerr (@dots{}, @var{flag}) +## @deftypefnx {Function File} {[@var{num}, @var{rate} @var{ind}] =} symerr (@dots{}) +## +## Compares two matrices and returns the number of symbol errors and the +## symbol error rate. The variables @var{a} and @var{b} can be either: +## +## @table @asis +## @item Both matrices +## In this case both matrices must be the same size and then by default the +## return values @var{num} and @var{rate} are the overall number of symbol +## errors and the overall symbol error rate. +## @item One column vector +## In this case the column vector is used for symbol error comparison +## column-wise with the matrix. The returned values @var{num} and @var{rate} +## are then row vectors containing the number of symbol errors and the symbol +## error rate for each of the column-wise comparisons. The number of rows in +## the matrix must be the same as the length of the column vector +## @item One row vector +## In this case the row vector is used for symbol error comparison row-wise +## with the matrix. The returned values @var{num} and @var{rate} are then +## column vectors containing the number of symbol errors and the symbol error +## rate for each of the row-wise comparisons. The number of columns in the +## matrix must be the same as the length of the row vector +## @end table +## +## This behavior can be overridden with the variable @var{flag}. @var{flag} +## can take the value "column-wise", "row-wise" or "overall". A column-wise +## comparison is not possible with a row vector and visa-versa. +## @end deftypefn + +function [num, rate, ind] = symerr (a, b, _flag) + + if (nargin < 2 || nargin > 4) + print_usage (); + endif + if (! (!any (isinf (a(:))) && !any (isnan (a(:))) && all (isreal (a(:))) + && all (a(:) == fix (a(:))) && all (a(:) >= 0))) + error ("symerr: all elements of A must be non-negative integers"); + endif + if (! (!any (isinf (b(:))) && !any (isnan (b(:))) && all (isreal (b(:))) + && all (b(:) == fix (b(:))) && all (b(:) >= 0))) + error ("symerr: all elements of B must be non-negative integers"); + endif + + [ar, ac] = size (a); + [br, bc] = size (b); + + if (ar == br && ac == bc) + type = "matrix"; + flag = "overall"; + c = 1; + elseif (any ([ar, br] == 1)) + type = "row"; + flag = "row"; + if (ac != bc) + error ("symerr: A and B must have the same number of columns for row-wise comparison"); + endif + if (ar == 1) + a = ones (br, 1) * a; + else + b = ones (ar, 1) * b; + endif + elseif (any ([ac, bc] == 1)) + type = "column"; + flag = "column"; + if (ar != br) + error ("symerr: A and B must have the same number of rows for column-wise comparison"); + endif + if (ac == 1) + a = a * ones (1, bc); + else + b = b * ones (1, ac); + endif + else + error ("symerr: A and B must have the same size"); + endif + + if (nargin > 2) + if (ischar (_flag)) + if (strcmp (_flag, "row-wise")) + if (strcmp (type, "column")) + error ("symerr: row-wise comparison not possible with column inputs"); + endif + flag = "row"; + elseif (strcmp (_flag, "column-wise")) + if (strcmp (type, "row")) + error ("symerr: column-wise comparison not possible with row inputs"); + endif + flag = "column"; + elseif (strcmp (_flag, "overall")) + flag = "overall"; + else + error ("symerr: invalid option '%s'", _flag); + endif + else + error ("symerr: FLAG must be a string"); + endif + endif + + ## Call the core error function to count the bit errors + ind = (__errcore__ (a, b) != 0); + + switch (flag) + case "row" + if (strcmp (type, "matrix") && ac == 1) + num = ind; + else + num = sum (ind')'; + endif + rate = num / max (ac, bc); + case "column" + if (strcmp (type, "matrix") && ar == 1) + num = ind; + else + num = sum (ind); + endif + rate = num / max (ar, br); + case "overall" + num = sum (sum (ind)); + rate = num / max (ar, br) / max (ac, bc); + otherwise + error ("symerr: invalid comparison type '%s'", flag); + endswitch + +endfunction + +%% Test input validation +%!error symerr () +%!error symerr (1) +%!error symerr (1, 2, 3, 4, 5) +%!error symerr (1, 1, 1) +%!error symerr (1, 1, "invalid") diff --git a/inst/systematize.m b/inst/systematize.m new file mode 100644 index 0000000..d5482ee --- /dev/null +++ b/inst/systematize.m @@ -0,0 +1,126 @@ +## Copyright (C) 2007 Muthiah Annamalai +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {} systematize (@var{G}) +## +## Given @var{G}, extract P parity check matrix. Assume row-operations in GF(2). +## @var{G} is of size KxN, when decomposed through row-operations into a @var{I} of size KxK +## identity matrix, and a parity check matrix @var{P} of size Kx(N-K). +## +## Most arbitrary code with a given generator matrix @var{G}, can be converted into its +## systematic form using this function. +## +## This function returns 2 values, first is default being @var{Gx} the systematic version of +## the @var{G} matrix, and then the parity check matrix @var{P}. +## +## @example +## @group +## g = [1 1 1 1; 1 1 0 1; 1 0 0 1]; +## [gx, p] = systematize (g); +## @result{} gx = [1 0 0 1; 0 1 0 0; 0 0 1 0]; +## @result{} p = [1 0 0]; +## @end group +## @end example +## @seealso{bchpoly, biterr} +## @end deftypefn + +function [G, P] = systematize (G) + + if (nargin != 1) + print_usage (); + endif + + [K, N] = size (G); + + if (K >= N) + error ("systematize: G must be a KxN matrix, with K < N"); + endif + + ## + ## gauss-jordan echelon formation, + ## and then back-operations to get I of size KxK + ## remaining is the P matrix. + ## + + for row = 1:K + + ## + ## pick a pivot for this row, by finding the + ## first of remaining rows that have non-zero element + ## in the pivot. + ## + + found_pivot = 0; + if (G(row,row) > 0) + found_pivot = 1; + else + ## + ## next step of Gauss-Jordan, you need to + ## re-sort the remaining rows, such that their + ## pivot element is non-zero. + ## + for idx = row+1:K + if (G(idx,row) > 0) + tmp = G(row,:); + G(row,:) = G(idx,:); + G(idx,:) = tmp; + found_pivot = 1; + break; + endif + endfor + endif + + ## + ## some linearly dependent problems: + ## + if (!found_pivot) + error ("systematize: could not systematize matrix G"); + return + endif + + ## + ## Gauss-Jordan method: + ## pick pivot element, then remove it + ## from the rest of the rows. + ## + for idx = row+1:K + if (G(idx,row) > 0) + G(idx,:) = mod (G(idx,:) + G(row,:), 2); + endif + endfor + + endfor + + ## + ## Now work-backward. + ## + for row = K:-1:2 + for idx = row-1:-1:1 + if (G(idx,row) > 0) + G(idx,:) = mod (G(idx,:) + G(row,:), 2); + endif + endfor + endfor + + #I = G(:,1:K); + P = G(:,K+1:end); + +endfunction + +%% Test input validation +%!error systematize () +%!error systematize (1, 2) +%!error systematize (eye (3)) diff --git a/inst/vec2mat.m b/inst/vec2mat.m new file mode 100644 index 0000000..8655eb1 --- /dev/null +++ b/inst/vec2mat.m @@ -0,0 +1,63 @@ +## Copyright (C) 2001 Laurent Mazet +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{m} =} vec2mat (@var{v}, @var{c}) +## @deftypefnx {Function File} {@var{m} =} vec2mat (@var{v}, @var{c}, @var{d}) +## @deftypefnx {Function File} {[@var{m}, @var{add}] =} vec2mat (@dots{}) +## +## Converts the vector @var{v} into a @var{c} column matrix with row priority +## arrangement and with the final column padded with the value @var{d} to the +## correct length. By default @var{d} is 0. The amount of padding added to +## the matrix is returned in @var{add}. +## @end deftypefn + +function [M, d] = vec2mat (V, c, val) + + switch (nargin) + case 1 + M = V; + return; + case 2 + val = 0; + case 3 + val = val; + otherwise + print_usage (); + endswitch + + V = V.'; + V = V(:); + + r = ceil (length (V) / c); + + d = r * c - length (V); + if (d != 0) + V = [V; val*ones(d, 1)]; + endif + + M = reshape (V, c, r).'; + +endfunction + +%!assert (vec2mat ([]), []) +%!assert (vec2mat (1), 1) +%!assert (vec2mat (1, 5), [1 0 0 0 0]) +%!assert (vec2mat (0:8), 0:8) +%!assert (vec2mat (0:8, 3), [0:2; 3:5; 6:8]) + +%% Test input validation +%!error vec2mat () +%!error vec2mat (1, 2, 3, 4) diff --git a/inst/wgn.m b/inst/wgn.m new file mode 100644 index 0000000..d045a8b --- /dev/null +++ b/inst/wgn.m @@ -0,0 +1,141 @@ +## Copyright (C) 2002 David Bateman +## +## This program is free software; you can redistribute it and/or modify it under +## the terms of the GNU General Public License as published by the Free Software +## Foundation; either version 3 of the License, or (at your option) any later +## version. +## +## This program 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 General Public License for more +## details. +## +## You should have received a copy of the GNU General Public License along with +## this program; if not, see . + +## -*- texinfo -*- +## @deftypefn {Function File} {@var{y} =} wgn (@var{m}, @var{n}, @var{p}) +## @deftypefnx {Function File} {@var{y} =} wgn (@var{m}, @var{n}, @var{p}, @var{imp}) +## @deftypefnx {Function File} {@var{y} =} wgn (@var{m}, @var{n}, @var{p}, @var{imp}, @var{seed}) +## @deftypefnx {Function File} {@var{y} =} wgn (@dots{}, @var{type}) +## @deftypefnx {Function File} {@var{y} =} wgn (@dots{}, @var{output}) +## +## Returns a M-by-N matrix @var{y} of white Gaussian noise. @var{p} specifies +## the power of the output noise, which is assumed to be referenced to an +## impedance of 1 Ohm, unless @var{imp} explicitly defines the impedance. +## +## If @var{seed} is defined then the randn function is seeded with this +## value. +## +## The arguments @var{type} and @var{output} must follow the above numerical +## arguments, but can be specified in any order. @var{type} specifies the +## units of @var{p}, and can be "dB", "dBW", "dBm" or "linear". "dB" is +## in fact the same as "dBW" and is keep as a misnomer of Matlab. The +## units of "linear" are in Watts. +## +## The @var{output} variable should be either "real" or "complex". If the +## output is complex then the power @var{p} is divided equally between the +## real and imaginary parts. +## +## @seealso{randn, awgn} +## @end deftypefn + +function y = wgn (m, n, p, varargin) + + if (nargin < 3 || nargin > 7) + print_usage (); + endif + + if (!isscalar (m) || !isreal (m) || m < 0 || !isscalar (n) || ... + !isreal (n) || n < 0) + error ("wgn: M and N must be positive integers"); + endif + + type = "dBW"; + out = "real"; + imp = 1; + seed = []; + narg = 0; + + for i = 1:length (varargin) + arg = varargin{i}; + if (ischar (arg)) + if (strcmp (arg, "real")) + out = "real"; + elseif (strcmp (arg, "complex")) + out = "complex"; + elseif (strcmp (arg, "dB")) + type = "dBW"; + elseif (strcmp (arg, "dBW")) + type = "dBW"; + elseif (strcmp (arg, "dBm")) + type = "dBm"; + elseif (strcmp (arg, "linear")) + type = "linear"; + else + error ("wgn: invalid argument '%s'", arg); + endif + else + narg++; + switch (narg) + case 1 + imp = arg; + case 2 + seed = arg; + otherwise + error ("wgn: too many arguments"); + endswitch + endif + endfor + + if (isempty (imp)) + imp = 1; + elseif (!isscalar (imp) || !isreal (imp) || imp < 0) + error ("wgn: IMP must be a non-negative scalar"); + endif + + if (!isempty (seed)) + if (! (isscalar (seed) && isreal (seed) && seed == fix (seed) && seed >= 0)) + error ("wgn: random SEED must be integer"); + endif + endif + + if (!isscalar (p) || !isreal (p)) + error ("wgn: P must be a scalar"); + endif + if (strcmp (type, "linear") && p < 0) + error ("wgn: P must be a non-negative scalar for TYPE \"linear\""); + endif + + if (strcmp (type, "dBW")) + np = 10^(p/10); + elseif (strcmp (type, "dBm")) + np = 10^((p - 30)/10); + elseif (strcmp (type, "linear")) + np = p; + endif + + if (!isempty (seed)) + randn ("state", seed); + endif + + if (strcmp (out, "complex")) + y = (sqrt (imp*np/2)) * (randn (m, n) + 1i*randn (m, n)); + else + y = (sqrt (imp*np)) * randn (m, n); + endif + +endfunction + +## Allow 30% error in standard deviation, due to randomness +%!assert (isreal (wgn (10, 10, 30, 1, "dBm", "real"))); +%!assert (iscomplex (wgn (10, 10, 30, 1, "dBm", "complex"))); +%!assert (abs (std (wgn (10000, 1, 30, 1, "dBm")) - 1) < 0.3); +%!assert (abs (std (wgn (10000, 1, 0, 1, "dBW")) - 1) < 0.3); +%!assert (abs (std (wgn (10000, 1, 1, 1, "linear")) - 1) < 0.3); + +%% Test input validation +%!error wgn (); +%!error wgn (1); +%!error wgn (1, 1); +%!error wgn (1, 1, 1, 1, 1, 1); diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 0000000..484ba49 --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,69 @@ +MKOCTFILE ?= @MKOCTFILE@ +OCTAVE ?= @OCTAVE@ +SED ?= @SED@ + +HDF5_CPPFLAGS = @HDF5_CFLAGS@ +HDF5_LIBS = @HDF5_LIBS@ +PKG_CPPFLAGS = -DGALOIS_DISP_PRIVATES @DEFS@ + +OCT_FILES = \ + __errcore__.oct \ + __gfweight__.oct \ + cyclgen.oct \ + cyclpoly.oct \ + genqamdemod.oct \ + gf.oct \ + isprimitive.oct \ + primpoly.oct \ + syndtable.oct + +GF_OBJECTS = \ + galois-def.o \ + galois.o \ + galoisfield.o \ + gf.o \ + op-gm-gm.o \ + op-gm-m.o \ + op-gm-s.o \ + op-m-gm.o \ + op-s-gm.o \ + ov-galois.o + +GF_HEADERS = \ + galois-def.h \ + galois-ops.h \ + galois.h \ + galoisfield.h \ + ov-galois.h + +OCT_SOURCES = $(patsubst %.oct,%.cc,$(OCT_FILES)) + +all: $(OCT_FILES) + +%.o: %.cc + $(MKOCTFILE) $(PKG_CPPFLAGS) -c $< -o $@ + +%.oct: %.cc + $(MKOCTFILE) $(PKG_CPPFLAGS) $< -o $@ + +gf.oct: $(GF_OBJECTS) + $(MKOCTFILE) $^ $(HDF5_LIBS) -o $@ + +ov-galois.o: PKG_CPPFLAGS += $(HDF5_CPPFLAGS) + +$(GF_OBJECTS): $(GF_HEADERS) + +PKG_ADD PKG_DEL: $(OCT_SOURCES) + $(SED) -n -e 's/.*$@: \(.*\)/\1/p' $^ > $@-t + mv $@-t $@ + +clean: + -rm -f *.o *.oct PKG_* + +distclean: clean + -rm -f Makefile config.h config.log config.status oct-alt-includes.h + +maintainer-clean: distclean + -rm -rf autom4te.cache configure config.h.in aclocal.m4 + +.PHONY: all clean distclean maintainer-clean diff --git a/src/__errcore__.cc b/src/__errcore__.cc new file mode 100644 index 0000000..2b81652 --- /dev/null +++ b/src/__errcore__.cc @@ -0,0 +1,84 @@ +//Copyright (C) 2003 David Bateman +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of the +// License, or (at your option) any later version. +// +// This program 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 +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, see +// . +// +// In addition to the terms of the GPL, you are permitted to link this +// program with any Open Source program, as defined by the Open Source +// Initiative (www.opensource.org) + +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +DEFUN_DLD (__errcore__, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{c} =} __errcore__ (@var{a}, @var{b})\n\ +Returns the number of bit errors comparing the matrices @var{a} and\n\ +@var{b}. These matrices must be of the same size. The return matrix @var{c}\n\ +will also be of the same size.\n\ +\n\ +This is an internal function of @code{biterr} and @code{symerr}. You should\n\ +use these functions instead.\n\ +@seealso{biterr, symerr}\n\ +@end deftypefn") +{ + octave_value retval; + + if (args.length () != 2) + { + print_usage (); + return retval; + } + + Matrix a = args(0).matrix_value (); + Matrix b = args(1).matrix_value (); + + if ((a.rows () != b.rows ()) || (a.cols () != b.cols ())) + { + error ("__errcore__: Matrix mismatch"); + return retval; + } + + unsigned int sz = (sizeof (unsigned int) << 3); + Matrix c (a.rows (), a.cols (), 0); + for (int i = 0; i < a.rows (); i++) + for (int j = 0; j < a.cols (); j++) + { + unsigned int tmp = (unsigned int)a(i,j) ^ (unsigned int)b(i,j); + if (tmp != 0) + for (unsigned int k=0; k < sz; k++) + if (tmp & (1<. +// +// In addition to the terms of the GPL, you are permitted to link this +// program with any Open Source program, as defined by the Open Source +// Initiative (www.opensource.org) + +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +static int +get_weight (const Array& codeword, const Matrix& gen, + int weight, int depth, int start, int n, int k) +{ + int retval = weight; + + for (int i = start; i < k ; i++) + { + OCTAVE_QUIT; + + Array new_codeword (codeword); + int tmp = 0; + for (int j = 0; j < n; j++) + if (new_codeword (j) ^= (char)gen(i,j)) + tmp++; + if (tmp < retval) + retval = tmp; + if (depth < retval) + retval = get_weight (new_codeword, gen, retval, depth+1, i+1, n, k); + } + return retval; +} + +DEFUN_DLD (__gfweight__, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{w} =} __gfweight__ (@var{gen})\n\ +Returns the minimum distance @var{w} of the generator matrix @var{gen}.\n\ +The codeword length is @var{k}.\n\ +\n\ +This is an internal function of @code{gfweight}. You should use\n\ +@code{gfweight} rather than use this function directly.\n\ +@seealso{gfweight}\n\ +@end deftypefn") +{ + + if (args.length () != 1) + { + print_usage (); + return octave_value (); + } + + Matrix gen = args(0).matrix_value (); + int k = gen.rows (); + int n = gen.columns (); + + if (k > 128) + { + octave_stdout << "__gfweight__: this is likely to take a very long time!!\n"; + OCTAVE__FLUSH_STDOUT (); + } + + Array codeword (dim_vector (n, 1), 0); + return octave_value ((double)get_weight (codeword, gen, n - k + 1, 1, + 0, n, k)); +} + +/* +%% Test input validation +%!error __gfweight__ () +%!error __gfweight__ (1, 2) +*/ + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/aclocal.m4 b/src/aclocal.m4 new file mode 100644 index 0000000..61edc67 --- /dev/null +++ b/src/aclocal.m4 @@ -0,0 +1,291 @@ +# generated automatically by aclocal 1.16.1 -*- Autoconf -*- + +# Copyright (C) 1996-2018 Free Software Foundation, Inc. + +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +m4_ifndef([AC_CONFIG_MACRO_DIRS], [m4_defun([_AM_CONFIG_MACRO_DIRS], [])m4_defun([AC_CONFIG_MACRO_DIRS], [_AM_CONFIG_MACRO_DIRS($@)])]) +dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*- +dnl serial 11 (pkg-config-0.29.1) +dnl +dnl Copyright © 2004 Scott James Remnant . +dnl Copyright © 2012-2015 Dan Nicholson +dnl +dnl This program is free software; you can redistribute it and/or modify +dnl it under the terms of the GNU General Public License as published by +dnl the Free Software Foundation; either version 2 of the License, or +dnl (at your option) any later version. +dnl +dnl This program is distributed in the hope that it will be useful, but +dnl WITHOUT ANY WARRANTY; without even the implied warranty of +dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +dnl General Public License for more details. +dnl +dnl You should have received a copy of the GNU General Public License +dnl along with this program; if not, write to the Free Software +dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +dnl 02111-1307, USA. +dnl +dnl As a special exception to the GNU General Public License, if you +dnl distribute this file as part of a program that contains a +dnl configuration script generated by Autoconf, you may include it under +dnl the same distribution terms that you use for the rest of that +dnl program. + +dnl PKG_PREREQ(MIN-VERSION) +dnl ----------------------- +dnl Since: 0.29 +dnl +dnl Verify that the version of the pkg-config macros are at least +dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's +dnl installed version of pkg-config, this checks the developer's version +dnl of pkg.m4 when generating configure. +dnl +dnl To ensure that this macro is defined, also add: +dnl m4_ifndef([PKG_PREREQ], +dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])]) +dnl +dnl See the "Since" comment for each macro you use to see what version +dnl of the macros you require. +m4_defun([PKG_PREREQ], +[m4_define([PKG_MACROS_VERSION], [0.29.1]) +m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1, + [m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])]) +])dnl PKG_PREREQ + +dnl PKG_PROG_PKG_CONFIG([MIN-VERSION]) +dnl ---------------------------------- +dnl Since: 0.16 +dnl +dnl Search for the pkg-config tool and set the PKG_CONFIG variable to +dnl first found in the path. Checks that the version of pkg-config found +dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is +dnl used since that's the first version where most current features of +dnl pkg-config existed. +AC_DEFUN([PKG_PROG_PKG_CONFIG], +[m4_pattern_forbid([^_?PKG_[A-Z_]+$]) +m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$]) +m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$]) +AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility]) +AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path]) +AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path]) + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + AC_PATH_TOOL([PKG_CONFIG], [pkg-config]) +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=m4_default([$1], [0.9.0]) + AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version]) + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) + PKG_CONFIG="" + fi +fi[]dnl +])dnl PKG_PROG_PKG_CONFIG + +dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------------------------------- +dnl Since: 0.18 +dnl +dnl Check to see whether a particular set of modules exists. Similar to +dnl PKG_CHECK_MODULES(), but does not set variables or print errors. +dnl +dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +dnl only at the first occurence in configure.ac, so if the first place +dnl it's called might be skipped (such as if it is within an "if", you +dnl have to call PKG_CHECK_EXISTS manually +AC_DEFUN([PKG_CHECK_EXISTS], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +if test -n "$PKG_CONFIG" && \ + AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then + m4_default([$2], [:]) +m4_ifvaln([$3], [else + $3])dnl +fi]) + +dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES]) +dnl --------------------------------------------- +dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting +dnl pkg_failed based on the result. +m4_define([_PKG_CONFIG], +[if test -n "$$1"; then + pkg_cv_[]$1="$$1" + elif test -n "$PKG_CONFIG"; then + PKG_CHECK_EXISTS([$3], + [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes ], + [pkg_failed=yes]) + else + pkg_failed=untried +fi[]dnl +])dnl _PKG_CONFIG + +dnl _PKG_SHORT_ERRORS_SUPPORTED +dnl --------------------------- +dnl Internal check to see if pkg-config supports short errors. +AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG]) +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi[]dnl +])dnl _PKG_SHORT_ERRORS_SUPPORTED + + +dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl -------------------------------------------------------------- +dnl Since: 0.4.0 +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES might not happen, you should be sure to include an +dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac +AC_DEFUN([PKG_CHECK_MODULES], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl +AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl + +pkg_failed=no +AC_MSG_CHECKING([for $1]) + +_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2]) +_PKG_CONFIG([$1][_LIBS], [libs], [$2]) + +m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS +and $1[]_LIBS to avoid the need to call pkg-config. +See the pkg-config man page for more details.]) + +if test $pkg_failed = yes; then + AC_MSG_RESULT([no]) + _PKG_SHORT_ERRORS_SUPPORTED + if test $_pkg_short_errors_supported = yes; then + $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1` + else + $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD + + m4_default([$4], [AC_MSG_ERROR( +[Package requirements ($2) were not met: + +$$1_PKG_ERRORS + +Consider adjusting the PKG_CONFIG_PATH environment variable if you +installed software in a non-standard prefix. + +_PKG_TEXT])[]dnl + ]) +elif test $pkg_failed = untried; then + AC_MSG_RESULT([no]) + m4_default([$4], [AC_MSG_FAILURE( +[The pkg-config script could not be found or is too old. Make sure it +is in your PATH or set the PKG_CONFIG environment variable to the full +path to pkg-config. + +_PKG_TEXT + +To get pkg-config, see .])[]dnl + ]) +else + $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS + $1[]_LIBS=$pkg_cv_[]$1[]_LIBS + AC_MSG_RESULT([yes]) + $3 +fi[]dnl +])dnl PKG_CHECK_MODULES + + +dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], +dnl [ACTION-IF-NOT-FOUND]) +dnl --------------------------------------------------------------------- +dnl Since: 0.29 +dnl +dnl Checks for existence of MODULES and gathers its build flags with +dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags +dnl and VARIABLE-PREFIX_LIBS from --libs. +dnl +dnl Note that if there is a possibility the first call to +dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to +dnl include an explicit call to PKG_PROG_PKG_CONFIG in your +dnl configure.ac. +AC_DEFUN([PKG_CHECK_MODULES_STATIC], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +_save_PKG_CONFIG=$PKG_CONFIG +PKG_CONFIG="$PKG_CONFIG --static" +PKG_CHECK_MODULES($@) +PKG_CONFIG=$_save_PKG_CONFIG[]dnl +])dnl PKG_CHECK_MODULES_STATIC + + +dnl PKG_INSTALLDIR([DIRECTORY]) +dnl ------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable pkgconfigdir as the location where a module +dnl should install pkg-config .pc files. By default the directory is +dnl $libdir/pkgconfig, but the default can be changed by passing +dnl DIRECTORY. The user can override through the --with-pkgconfigdir +dnl parameter. +AC_DEFUN([PKG_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([pkgconfigdir], + [AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],, + [with_pkgconfigdir=]pkg_default) +AC_SUBST([pkgconfigdir], [$with_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_INSTALLDIR + + +dnl PKG_NOARCH_INSTALLDIR([DIRECTORY]) +dnl -------------------------------- +dnl Since: 0.27 +dnl +dnl Substitutes the variable noarch_pkgconfigdir as the location where a +dnl module should install arch-independent pkg-config .pc files. By +dnl default the directory is $datadir/pkgconfig, but the default can be +dnl changed by passing DIRECTORY. The user can override through the +dnl --with-noarch-pkgconfigdir parameter. +AC_DEFUN([PKG_NOARCH_INSTALLDIR], +[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])]) +m4_pushdef([pkg_description], + [pkg-config arch-independent installation directory @<:@]pkg_default[@:>@]) +AC_ARG_WITH([noarch-pkgconfigdir], + [AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],, + [with_noarch_pkgconfigdir=]pkg_default) +AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir]) +m4_popdef([pkg_default]) +m4_popdef([pkg_description]) +])dnl PKG_NOARCH_INSTALLDIR + + +dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE, +dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +dnl ------------------------------------------- +dnl Since: 0.28 +dnl +dnl Retrieves the value of the pkg-config variable for the given module. +AC_DEFUN([PKG_CHECK_VAR], +[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl +AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl + +_PKG_CONFIG([$1], [variable="][$3]["], [$2]) +AS_VAR_COPY([$1], [pkg_cv_][$1]) + +AS_VAR_IF([$1], [""], [$5], [$4])dnl +])dnl PKG_CHECK_VAR + +m4_include([m4/octave-forge.m4]) diff --git a/src/base-lu.cc b/src/base-lu.cc new file mode 100644 index 0000000..1319a34 --- /dev/null +++ b/src/base-lu.cc @@ -0,0 +1,191 @@ +/* + +Copyright (C) 1996-2015 John W. Eaton +Copyright (C) 2009 VZLU Prague + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +Octave 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 General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, see +. + +*/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "base-lu.h" + +template +base_lu::base_lu (const lu_type& l, const lu_type& u, + const PermMatrix& p) + : a_fact (u), l_fact (l), ipvt (p.transpose ().col_perm_vec ()) +{ + if (l.columns () != u.rows ()) + (*current_liboctave_error_handler) ("lu: dimension mismatch"); +} + +template +bool +base_lu :: packed (void) const +{ + return l_fact.dims () == dim_vector (); +} + +template +void +base_lu :: unpack (void) +{ + if (packed ()) + { + l_fact = L (); + a_fact = U (); // FIXME: sub-optimal + ipvt = getp (); + } +} + +template +lu_type +base_lu :: L (void) const +{ + if (packed ()) + { + octave_idx_type a_nr = a_fact.rows (); + octave_idx_type a_nc = a_fact.cols (); + octave_idx_type mn = (a_nr < a_nc ? a_nr : a_nc); + + lu_type l (a_nr, mn, lu_elt_type (0.0)); + + for (octave_idx_type i = 0; i < a_nr; i++) + { + if (i < a_nc) + l.xelem (i, i) = 1.0; + + for (octave_idx_type j = 0; j < (i < a_nc ? i : a_nc); j++) + l.xelem (i, j) = a_fact.xelem (i, j); + } + + return l; + } + else + return l_fact; +} + +template +lu_type +base_lu :: U (void) const +{ + if (packed ()) + { + octave_idx_type a_nr = a_fact.rows (); + octave_idx_type a_nc = a_fact.cols (); + octave_idx_type mn = (a_nr < a_nc ? a_nr : a_nc); + + lu_type u (mn, a_nc, lu_elt_type (0.0)); + + for (octave_idx_type i = 0; i < mn; i++) + { + for (octave_idx_type j = i; j < a_nc; j++) + u.xelem (i, j) = a_fact.xelem (i, j); + } + + return u; + } + else + return a_fact; +} + +template +lu_type +base_lu :: Y (void) const +{ + if (! packed ()) + (*current_liboctave_error_handler) + ("lu: Y () not implemented for unpacked form"); + return a_fact; +} + +template +Array +base_lu :: getp (void) const +{ + if (packed ()) + { + octave_idx_type a_nr = a_fact.rows (); + + Array pvt (dim_vector (a_nr, 1)); + + for (octave_idx_type i = 0; i < a_nr; i++) + pvt.xelem (i) = i; + + for (octave_idx_type i = 0; i < ipvt.numel (); i++) + { + octave_idx_type k = ipvt.xelem (i); + + if (k != i) + { + octave_idx_type tmp = pvt.xelem (k); + pvt.xelem (k) = pvt.xelem (i); + pvt.xelem (i) = tmp; + } + } + + return pvt; + } + else + return ipvt; +} + +template +PermMatrix +base_lu :: P (void) const +{ + return PermMatrix (getp (), false); +} + +template +ColumnVector +base_lu :: P_vec (void) const +{ + octave_idx_type a_nr = a_fact.rows (); + + ColumnVector p (a_nr); + + Array pvt = getp (); + + for (octave_idx_type i = 0; i < a_nr; i++) + p.xelem (i) = static_cast (pvt.xelem (i) + 1); + + return p; +} + +template +bool +base_lu::regular (void) const +{ + bool retval = true; + + octave_idx_type k = std::min (a_fact.rows (), a_fact.columns ()); + + for (octave_idx_type i = 0; i < k; i++) + { + if (a_fact(i, i) == lu_elt_type ()) + { + retval = false; + break; + } + } + + return retval; +} diff --git a/src/base-lu.h b/src/base-lu.h new file mode 100644 index 0000000..f11f625 --- /dev/null +++ b/src/base-lu.h @@ -0,0 +1,87 @@ +/* + +Copyright (C) 1996-2015 John W. Eaton +Copyright (C) 2009 VZLU Prague + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +Octave 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 General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, see +. + +*/ + +#if !defined (octave_base_lu_h) +#define octave_base_lu_h 1 + +#include "MArray.h" +#include "dColVector.h" +#include "PermMatrix.h" + +template +class +base_lu +{ +public: + + typedef typename lu_type::element_type lu_elt_type; + + base_lu (void) + : a_fact (), l_fact (), ipvt () { } + + base_lu (const base_lu& a) + : a_fact (a.a_fact), l_fact (a.l_fact), ipvt (a.ipvt) { } + + base_lu (const lu_type& l, const lu_type& u, + const PermMatrix& p); + + base_lu& operator = (const base_lu& a) + { + if (this != &a) + { + a_fact = a.a_fact; + l_fact = a.l_fact; + ipvt = a.ipvt; + } + return *this; + } + + virtual ~base_lu (void) { } + + bool packed (void) const; + + void unpack (void); + + lu_type L (void) const; + + lu_type U (void) const; + + lu_type Y (void) const; + + PermMatrix P (void) const; + + ColumnVector P_vec (void) const; + + bool regular (void) const; + +protected: + + Array getp (void) const; + + lu_type a_fact; + lu_type l_fact; + + Array ipvt; +}; + +#endif diff --git a/src/bootstrap b/src/bootstrap new file mode 100755 index 0000000..80f4967 --- /dev/null +++ b/src/bootstrap @@ -0,0 +1,10 @@ +#!/bin/bash +## Octave-Forge: package bootstrap script +## Run this to generate the configure script + +set -e # halt if unhandled error +aclocal +autoconf # generate configure script +autoheader -f +rm -rf autom4te.cache + diff --git a/src/config.h.in b/src/config.h.in new file mode 100644 index 0000000..c0f563b --- /dev/null +++ b/src/config.h.in @@ -0,0 +1,128 @@ +/* config.h.in. Generated from configure.ac by autoheader. */ + +#include "undef-ah-octave.h" + +/* macro for alternative Octave symbols */ +#undef DELOCTAVE__ERR_SQUARE_MATRIX_REQUIRED + +/* Define to 1 if you have the header file. */ +#undef HAVE_HDF5_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OCTAVE_BASE_LU_H + +/* Define if have gripe_load and gripe_save */ +#undef HAVE_OCTAVE_BASE_VALUE_GRIPE_LOAD_SAVE + +/* Define if octave_base_value::print is const-qualified */ +#undef HAVE_OCTAVE_BASE_VALUE_PRINT_CONST + +/* Define to 1 if you have the header file. */ +#undef HAVE_OCTAVE_ERRWARN_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OCTAVE_GRIPES_H + +/* Define if have octave_hdf5_id */ +#undef HAVE_OCTAVE_HDF5_ID_TYPE + +/* Define to 1 if you have the header file. */ +#undef HAVE_OCTAVE_INTERPRETER_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OCTAVE_LS_OCT_ASCII_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OCTAVE_LS_OCT_TEXT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OCTAVE_LU_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OCTAVE_OCT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OCTAVE_OCT_OBJ_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_OCTAVE_OVL_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the header file. */ +#undef HAVE_UNISTD_H + +/* macro for alternative Octave symbols */ +#undef OCTAVE_MACH_INFO_FLOAT_FORMAT + +/* macro for alternative Octave symbols */ +#undef OCTAVE__ERR_INVALID_CONVERSION + +/* macro for alternative Octave symbols */ +#undef OCTAVE__ERR_NONCONFORMANT + +/* macro for alternative Octave symbols */ +#undef OCTAVE__ERR_WRONG_TYPE_ARG + +/* macro for alternative Octave symbols */ +#undef OCTAVE__FLUSH_STDOUT + +/* macro for alternative Octave symbols */ +#undef OCTAVE__WARN_INVALID_CONVERSION + +/* macro for alternative Octave symbols */ +#undef OV_ISCOMPLEX + +/* macro for alternative Octave symbols */ +#undef OV_ISEMPTY + +/* macro for alternative Octave symbols */ +#undef OV_ISNUMERIC + +/* macro for alternative Octave symbols */ +#undef OV_ISREAL + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the home page for this package. */ +#undef PACKAGE_URL + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +#include "oct-alt-includes.h" diff --git a/src/configure b/src/configure new file mode 100755 index 0000000..1ee0f33 --- /dev/null +++ b/src/configure @@ -0,0 +1,5359 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.69 for Octave-Forge communications package 0. +# +# +# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc. +# +# +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + +# Use a proper internal environment variable to ensure we don't fall + # into an infinite loop, continuously re-executing ourselves. + if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then + _as_can_reexec=no; export _as_can_reexec; + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +as_fn_exit 255 + fi + # We don't want this to propagate to other subprocesses. + { _as_can_reexec=; unset _as_can_reexec;} +if test "x$CONFIG_SHELL" = x; then + as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which + # is contrary to our usage. Disable this feature. + alias -g '\${1+\"\$@\"}'='\"\$@\"' + setopt NO_GLOB_SUBST +else + case \`(set -o) 2>/dev/null\` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi +" + as_required="as_fn_return () { (exit \$1); } +as_fn_success () { as_fn_return 0; } +as_fn_failure () { as_fn_return 1; } +as_fn_ret_success () { return 0; } +as_fn_ret_failure () { return 1; } + +exitcode=0 +as_fn_success || { exitcode=1; echo as_fn_success failed.; } +as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; } +as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; } +as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; } +if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then : + +else + exitcode=1; echo positional parameters were not saved. +fi +test x\$exitcode = x0 || exit 1 +test -x / || exit 1" + as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO + as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO + eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && + test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 +test \$(( 1 + 1 )) = 2 || exit 1" + if (eval "$as_required") 2>/dev/null; then : + as_have_required=yes +else + as_have_required=no +fi + if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then : + +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +as_found=false +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + as_found=: + case $as_dir in #( + /*) + for as_base in sh bash ksh sh5; do + # Try only shells that exist, to save several forks. + as_shell=$as_dir/$as_base + if { test -f "$as_shell" || test -f "$as_shell.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then : + CONFIG_SHELL=$as_shell as_have_required=yes + if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then : + break 2 +fi +fi + done;; + esac + as_found=false +done +$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } && + { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then : + CONFIG_SHELL=$SHELL as_have_required=yes +fi; } +IFS=$as_save_IFS + + + if test "x$CONFIG_SHELL" != x; then : + export CONFIG_SHELL + # We cannot yet assume a decent shell, so we have to provide a +# neutralization value for shells without unset; and this also +# works around shells that cannot unset nonexistent variables. +# Preserve -v and -x to the replacement shell. +BASH_ENV=/dev/null +ENV=/dev/null +(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV +case $- in # (((( + *v*x* | *x*v* ) as_opts=-vx ;; + *v* ) as_opts=-v ;; + *x* ) as_opts=-x ;; + * ) as_opts= ;; +esac +exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"} +# Admittedly, this is quite paranoid, since all the known shells bail +# out after a failed `exec'. +$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2 +exit 255 +fi + + if test x$as_have_required = xno; then : + $as_echo "$0: This script requires a shell more modern than all" + $as_echo "$0: the shells that I found on your system." + if test x${ZSH_VERSION+set} = xset ; then + $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should" + $as_echo "$0: be upgraded to zsh 4.3.4 or later." + else + $as_echo "$0: Please tell bug-autoconf@gnu.org about your system, +$0: including any error possibly output before this +$0: message. Then install a modern shell, or manually run +$0: the script under such a shell if you do have one." + fi + exit 1 +fi +fi +fi +SHELL=${CONFIG_SHELL-/bin/sh} +export SHELL +# Unset more variables known to interfere with behavior of common tools. +CLICOLOR_FORCE= GREP_OPTIONS= +unset CLICOLOR_FORCE GREP_OPTIONS + +## --------------------- ## +## M4sh Shell Functions. ## +## --------------------- ## +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + + + as_lineno_1=$LINENO as_lineno_1a=$LINENO + as_lineno_2=$LINENO as_lineno_2a=$LINENO + eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" && + test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || { + # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-) + sed -n ' + p + /[$]LINENO/= + ' <$as_myself | + sed ' + s/[$]LINENO.*/&-/ + t lineno + b + :lineno + N + :loop + s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/ + t loop + s/-\n.*// + ' >$as_me.lineno && + chmod +x "$as_me.lineno" || + { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; } + + # If we had to re-execute with $CONFIG_SHELL, we're ensured to have + # already done that, so ensure we don't try to do so again and fall + # in an infinite loop. This has already happened in practice. + _as_can_reexec=no; export _as_can_reexec + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensitive to this). + . "./$as_me.lineno" + # Exit status is that of the last command. + exit +} + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +test -n "$DJDIR" || exec 7<&0 &1 + +# Name of the host. +# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_clean_files= +ac_config_libobj_dir=. +LIBOBJS= +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= + +# Identity of this package. +PACKAGE_NAME='Octave-Forge communications package' +PACKAGE_TARNAME='octave-forge-communications-package' +PACKAGE_VERSION='0' +PACKAGE_STRING='Octave-Forge communications package 0' +PACKAGE_BUGREPORT='' +PACKAGE_URL='' + +# Factoring default headers for most tests. +ac_includes_default="\ +#include +#ifdef HAVE_SYS_TYPES_H +# include +#endif +#ifdef HAVE_SYS_STAT_H +# include +#endif +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif +#ifdef HAVE_STRING_H +# if !defined STDC_HEADERS && defined HAVE_MEMORY_H +# include +# endif +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#ifdef HAVE_INTTYPES_H +# include +#endif +#ifdef HAVE_STDINT_H +# include +#endif +#ifdef HAVE_UNISTD_H +# include +#endif" + +ac_subst_vars='LTLIBOBJS +LIBOBJS +HDF5_LIBS +HDF5_CFLAGS +PKG_CONFIG_LIBDIR +PKG_CONFIG_PATH +PKG_CONFIG +EGREP +GREP +CXXCPP +SED +OBJEXT +EXEEXT +ac_ct_CXX +CPPFLAGS +LDFLAGS +CXXFLAGS +CXX +OCTAVE +MKOCTFILE +target_alias +host_alias +build_alias +LIBS +ECHO_T +ECHO_N +ECHO_C +DEFS +mandir +localedir +libdir +psdir +pdfdir +dvidir +htmldir +infodir +docdir +oldincludedir +includedir +runstatedir +localstatedir +sharedstatedir +sysconfdir +datadir +datarootdir +libexecdir +sbindir +bindir +program_transform_name +prefix +exec_prefix +PACKAGE_URL +PACKAGE_BUGREPORT +PACKAGE_STRING +PACKAGE_VERSION +PACKAGE_TARNAME +PACKAGE_NAME +PATH_SEPARATOR +SHELL' +ac_subst_files='' +ac_user_opts=' +enable_option_checking +' + ac_precious_vars='build_alias +host_alias +target_alias +MKOCTFILE +OCTAVE +CXX +CXXFLAGS +LDFLAGS +LIBS +CPPFLAGS +CCC +CXXCPP +PKG_CONFIG +PKG_CONFIG_PATH +PKG_CONFIG_LIBDIR +HDF5_CFLAGS +HDF5_LIBS' + + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +ac_unrecognized_opts= +ac_unrecognized_sep= +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +# (The list follows the same order as the GNU Coding Standards.) +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datarootdir='${prefix}/share' +datadir='${datarootdir}' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +runstatedir='${localstatedir}/run' +includedir='${prefix}/include' +oldincludedir='/usr/include' +docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' +infodir='${datarootdir}/info' +htmldir='${docdir}' +dvidir='${docdir}' +pdfdir='${docdir}' +psdir='${docdir}' +libdir='${exec_prefix}/lib' +localedir='${datarootdir}/locale' +mandir='${datarootdir}/man' + +ac_prev= +ac_dashdash= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval $ac_prev=\$ac_option + ac_prev= + continue + fi + + case $ac_option in + *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;; + *=) ac_optarg= ;; + *) ac_optarg=yes ;; + esac + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_dashdash$ac_option in + --) + ac_dashdash=yes ;; + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=*) + datadir=$ac_optarg ;; + + -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \ + | --dataroo | --dataro | --datar) + ac_prev=datarootdir ;; + -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \ + | --dataroot=* | --dataroo=* | --dataro=* | --datar=*) + datarootdir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=no ;; + + -docdir | --docdir | --docdi | --doc | --do) + ac_prev=docdir ;; + -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*) + docdir=$ac_optarg ;; + + -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv) + ac_prev=dvidir ;; + -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*) + dvidir=$ac_optarg ;; + + -enable-* | --enable-*) + ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid feature name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"enable_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval enable_$ac_useropt=\$ac_optarg ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht) + ac_prev=htmldir ;; + -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \ + | --ht=*) + htmldir=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localedir | --localedir | --localedi | --localed | --locale) + ac_prev=localedir ;; + -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*) + localedir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst | --locals) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd) + ac_prev=pdfdir ;; + -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*) + pdfdir=$ac_optarg ;; + + -psdir | --psdir | --psdi | --psd | --ps) + ac_prev=psdir ;; + -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*) + psdir=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -runstatedir | --runstatedir | --runstatedi | --runstated \ + | --runstate | --runstat | --runsta | --runst | --runs \ + | --run | --ru | --r) + ac_prev=runstatedir ;; + -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ + | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ + | --run=* | --ru=* | --r=*) + runstatedir=$ac_optarg ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=\$ac_optarg ;; + + -without-* | --without-*) + ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null && + as_fn_error $? "invalid package name: $ac_useropt" + ac_useropt_orig=$ac_useropt + ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'` + case $ac_user_opts in + *" +"with_$ac_useropt" +"*) ;; + *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig" + ac_unrecognized_sep=', ';; + esac + eval with_$ac_useropt=no ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) as_fn_error $? "unrecognized option: \`$ac_option' +Try \`$0 --help' for more information" + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + case $ac_envvar in #( + '' | [0-9]* | *[!_$as_cr_alnum]* ) + as_fn_error $? "invalid variable name: \`$ac_envvar'" ;; + esac + eval $ac_envvar=\$ac_optarg + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}" + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + as_fn_error $? "missing argument to $ac_option" +fi + +if test -n "$ac_unrecognized_opts"; then + case $enable_option_checking in + no) ;; + fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;; + *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;; + esac +fi + +# Check all directory arguments for consistency. +for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ + datadir sysconfdir sharedstatedir localstatedir includedir \ + oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ + libdir localedir mandir runstatedir +do + eval ac_val=\$$ac_var + # Remove trailing slashes. + case $ac_val in + */ ) + ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'` + eval $ac_var=\$ac_val;; + esac + # Be sure to have absolute directory names. + case $ac_val in + [\\/$]* | ?:[\\/]* ) continue;; + NONE | '' ) case $ac_var in *prefix ) continue;; esac;; + esac + as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val" +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +ac_pwd=`pwd` && test -n "$ac_pwd" && +ac_ls_di=`ls -di .` && +ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` || + as_fn_error $? "working directory cannot be determined" +test "X$ac_ls_di" = "X$ac_pwd_ls_di" || + as_fn_error $? "pwd does not report name of working directory" + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then the parent directory. + ac_confdir=`$as_dirname -- "$as_myself" || +$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_myself" : 'X\(//\)[^/]' \| \ + X"$as_myself" : 'X\(//\)$' \| \ + X"$as_myself" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_myself" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r "$srcdir/$ac_unique_file"; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r "$srcdir/$ac_unique_file"; then + test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .." + as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir" +fi +ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work" +ac_abs_confdir=`( + cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg" + pwd)` +# When building in place, set srcdir=. +if test "$ac_abs_confdir" = "$ac_pwd"; then + srcdir=. +fi +# Remove unnecessary trailing slashes from srcdir. +# Double slashes in file names in object file debugging info +# mess up M-x gdb in Emacs. +case $srcdir in +*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;; +esac +for ac_var in $ac_precious_vars; do + eval ac_env_${ac_var}_set=\${${ac_var}+set} + eval ac_env_${ac_var}_value=\$${ac_var} + eval ac_cv_env_${ac_var}_set=\${${ac_var}+set} + eval ac_cv_env_${ac_var}_value=\$${ac_var} +done + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures Octave-Forge communications package 0 to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking ...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --datarootdir=DIR read-only arch.-independent data root [PREFIX/share] + --datadir=DIR read-only architecture-independent data [DATAROOTDIR] + --infodir=DIR info documentation [DATAROOTDIR/info] + --localedir=DIR locale-dependent data [DATAROOTDIR/locale] + --mandir=DIR man documentation [DATAROOTDIR/man] + --docdir=DIR documentation root + [DATAROOTDIR/doc/octave-forge-communications-package] + --htmldir=DIR html documentation [DOCDIR] + --dvidir=DIR dvi documentation [DOCDIR] + --pdfdir=DIR pdf documentation [DOCDIR] + --psdir=DIR ps documentation [DOCDIR] +_ACEOF + + cat <<\_ACEOF +_ACEOF +fi + +if test -n "$ac_init_help"; then + case $ac_init_help in + short | recursive ) echo "Configuration of Octave-Forge communications package 0:";; + esac + cat <<\_ACEOF + +Some influential environment variables: + MKOCTFILE mkoctfile compiler helper command + OCTAVE Octave interpreter command + CXX C++ compiler command + CXXFLAGS C++ compiler flags + LDFLAGS linker flags, e.g. -L if you have libraries in a + nonstandard directory + LIBS libraries to pass to the linker, e.g. -l + CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I if + you have headers in a nonstandard directory + CXXCPP C++ preprocessor + PKG_CONFIG path to pkg-config utility + PKG_CONFIG_PATH + directories to add to pkg-config's search path + PKG_CONFIG_LIBDIR + path overriding pkg-config's built-in search path + HDF5_CFLAGS C compiler flags for HDF5, overriding pkg-config + HDF5_LIBS linker flags for HDF5, overriding pkg-config + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +Report bugs to the package provider. +_ACEOF +ac_status=$? +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d "$ac_dir" || + { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } || + continue + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + cd "$ac_dir" || { ac_status=$?; continue; } + # Check for guested configure. + if test -f "$ac_srcdir/configure.gnu"; then + echo && + $SHELL "$ac_srcdir/configure.gnu" --help=recursive + elif test -f "$ac_srcdir/configure"; then + echo && + $SHELL "$ac_srcdir/configure" --help=recursive + else + $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi || ac_status=$? + cd "$ac_pwd" || { ac_status=$?; break; } + done +fi + +test -n "$ac_init_help" && exit $ac_status +if $ac_init_version; then + cat <<\_ACEOF +Octave-Forge communications package configure 0 +generated by GNU Autoconf 2.69 + +Copyright (C) 2012 Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit +fi + +## ------------------------ ## +## Autoconf initialization. ## +## ------------------------ ## + +# ac_fn_cxx_try_compile LINENO +# ---------------------------- +# Try to compile conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext + if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest.$ac_objext; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_compile + +# ac_fn_cxx_try_cpp LINENO +# ------------------------ +# Try to preprocess conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_cpp () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_cpp conftest.$ac_ext" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } > conftest.i && { + test -z "$ac_cxx_preproc_warn_flag$ac_cxx_werror_flag" || + test ! -s conftest.err + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_cpp + +# ac_fn_cxx_check_header_mongrel LINENO HEADER VAR INCLUDES +# --------------------------------------------------------- +# Tests whether HEADER exists, giving a warning if it cannot be compiled using +# the include files in INCLUDES and setting the cache variable VAR +# accordingly. +ac_fn_cxx_check_header_mongrel () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if eval \${$3+:} false; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +else + # Is the header compilable? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5 +$as_echo_n "checking $2 usability... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_header_compiler=yes +else + ac_header_compiler=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5 +$as_echo "$ac_header_compiler" >&6; } + +# Is the header present? +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5 +$as_echo_n "checking $2 presence... " >&6; } +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include <$2> +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + ac_header_preproc=yes +else + ac_header_preproc=no +fi +rm -f conftest.err conftest.i conftest.$ac_ext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5 +$as_echo "$ac_header_preproc" >&6; } + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc:$ac_cxx_preproc_warn_flag in #(( + yes:no: ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5 +$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; + no:yes:* ) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5 +$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5 +$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5 +$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5 +$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5 +$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;} + ;; +esac + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + eval "$3=\$ac_header_compiler" +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } +fi + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_cxx_check_header_mongrel + +# ac_fn_cxx_try_run LINENO +# ------------------------ +# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes +# that executables *can* be run. +ac_fn_cxx_try_run () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { ac_try='./conftest$ac_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then : + ac_retval=0 +else + $as_echo "$as_me: program exited with status $ac_status" >&5 + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=$ac_status +fi + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_run + +# ac_fn_cxx_check_header_compile LINENO HEADER VAR INCLUDES +# --------------------------------------------------------- +# Tests whether HEADER exists and can be compiled using the include files in +# INCLUDES, setting the cache variable VAR accordingly. +ac_fn_cxx_check_header_compile () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5 +$as_echo_n "checking for $2... " >&6; } +if eval \${$3+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +$4 +#include <$2> +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + eval "$3=yes" +else + eval "$3=no" +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +eval ac_res=\$$3 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5 +$as_echo "$ac_res" >&6; } + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + +} # ac_fn_cxx_check_header_compile + +# ac_fn_cxx_try_link LINENO +# ------------------------- +# Try to link conftest.$ac_ext, and return whether this succeeded. +ac_fn_cxx_try_link () +{ + as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + rm -f conftest.$ac_objext conftest$ac_exeext + if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + grep -v '^ *+' conftest.err >conftest.er1 + cat conftest.er1 >&5 + mv -f conftest.er1 conftest.err + fi + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } && { + test -z "$ac_cxx_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + test -x conftest$ac_exeext + }; then : + ac_retval=0 +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_retval=1 +fi + # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information + # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would + # interfere with the next link command; also delete a directory that is + # left behind by Apple's compiler. We do this before executing the actions. + rm -rf conftest.dSYM conftest_ipa8_conftest.oo + eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno + as_fn_set_status $ac_retval + +} # ac_fn_cxx_try_link +cat >config.log <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by Octave-Forge communications package $as_me 0, which was +generated by GNU Autoconf 2.69. Invocation command line was + + $ $0 $@ + +_ACEOF +exec 5>>config.log +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + $as_echo "PATH: $as_dir" + done +IFS=$as_save_IFS + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *\'*) + ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;; + 2) + as_fn_append ac_configure_args1 " '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + as_fn_append ac_configure_args " '$ac_arg'" + ;; + esac + done +done +{ ac_configure_args0=; unset ac_configure_args0;} +{ ac_configure_args1=; unset ac_configure_args1;} + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Use '\'' to represent an apostrophe within the trap. +# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + $as_echo "## ---------------- ## +## Cache variables. ## +## ---------------- ##" + echo + # The following way of writing the cache mishandles newlines in values, +( + for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + (set) 2>&1 | + case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + sed -n \ + "s/'\''/'\''\\\\'\'''\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p" + ;; #( + *) + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) + echo + + $as_echo "## ----------------- ## +## Output variables. ## +## ----------------- ##" + echo + for ac_var in $ac_subst_vars + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + + if test -n "$ac_subst_files"; then + $as_echo "## ------------------- ## +## File substitutions. ## +## ------------------- ##" + echo + for ac_var in $ac_subst_files + do + eval ac_val=\$$ac_var + case $ac_val in + *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;; + esac + $as_echo "$ac_var='\''$ac_val'\''" + done | sort + echo + fi + + if test -s confdefs.h; then + $as_echo "## ----------- ## +## confdefs.h. ## +## ----------- ##" + echo + cat confdefs.h + echo + fi + test "$ac_signal" != 0 && + $as_echo "$as_me: caught signal $ac_signal" + $as_echo "$as_me: exit $exit_status" + } >&5 + rm -f core *.core core.conftest.* && + rm -f -r conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status +' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -f -r conftest* confdefs.h + +$as_echo "/* confdefs.h */" > confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_URL "$PACKAGE_URL" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer an explicitly selected file to automatically selected ones. +ac_site_file1=NONE +ac_site_file2=NONE +if test -n "$CONFIG_SITE"; then + # We do not want a PATH search for config.site. + case $CONFIG_SITE in #(( + -*) ac_site_file1=./$CONFIG_SITE;; + */*) ac_site_file1=$CONFIG_SITE;; + *) ac_site_file1=./$CONFIG_SITE;; + esac +elif test "x$prefix" != xNONE; then + ac_site_file1=$prefix/share/config.site + ac_site_file2=$prefix/etc/config.site +else + ac_site_file1=$ac_default_prefix/share/config.site + ac_site_file2=$ac_default_prefix/etc/config.site +fi +for ac_site_file in "$ac_site_file1" "$ac_site_file2" +do + test "x$ac_site_file" = xNONE && continue + if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5 +$as_echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" \ + || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "failed to load site script $ac_site_file +See \`config.log' for more details" "$LINENO" 5; } + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special files + # actually), so we avoid doing that. DJGPP emulates it as a regular file. + if test /dev/null != "$cache_file" && test -f "$cache_file"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5 +$as_echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . "$cache_file";; + *) . "./$cache_file";; + esac + fi +else + { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5 +$as_echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in $ac_precious_vars; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val=\$ac_cv_env_${ac_var}_value + eval ac_new_val=\$ac_env_${ac_var}_value + case $ac_old_set,$ac_new_set in + set,) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5 +$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + # differences in whitespace do not lead to failure. + ac_old_val_w=`echo x $ac_old_val` + ac_new_val_w=`echo x $ac_new_val` + if test "$ac_old_val_w" != "$ac_new_val_w"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5 +$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + ac_cache_corrupted=: + else + { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5 +$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;} + eval $ac_var=\$ac_old_val + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5 +$as_echo "$as_me: former value: \`$ac_old_val'" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5 +$as_echo "$as_me: current value: \`$ac_new_val'" >&2;} + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) as_fn_append ac_configure_args " '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5 +$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;} + as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5 +fi +## -------------------- ## +## Main body of script. ## +## -------------------- ## + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +ac_config_headers="$ac_config_headers config.h" + + +# Avoid warnings for redefining AH-generated preprocessor symbols of +# Octave. + + + + + + +# Extract the first word of "mkoctfile", so it can be a program name with args. +set dummy mkoctfile; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_MKOCTFILE+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$MKOCTFILE"; then + ac_cv_prog_MKOCTFILE="$MKOCTFILE" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_MKOCTFILE="mkoctfile" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +MKOCTFILE=$ac_cv_prog_MKOCTFILE +if test -n "$MKOCTFILE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MKOCTFILE" >&5 +$as_echo "$MKOCTFILE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +# Extract the first word of "octave", so it can be a program name with args. +set dummy octave; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_OCTAVE+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$OCTAVE"; then + ac_cv_prog_OCTAVE="$OCTAVE" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_OCTAVE="octave" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +OCTAVE=$ac_cv_prog_OCTAVE +if test -n "$OCTAVE"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OCTAVE" >&5 +$as_echo "$OCTAVE" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -z "$CXX"; then + if test -n "$CCC"; then + CXX=$CCC + else + if test -n "$ac_tool_prefix"; then + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXX" >&5 +$as_echo "$CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in g++ c++ gpp aCC CC cxx cc++ cl.exe FCC KCC RCC xlC_r xlC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_ac_ct_CXX+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CXX" >&5 +$as_echo "$ac_ct_CXX" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$ac_ct_CXX" && break +done + + if test "x$ac_ct_CXX" = x; then + CXX="g++" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + CXX=$ac_ct_CXX + fi +fi + + fi +fi +# Provide some information about the compiler. +$as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler version" >&5 +set X $ac_compile +ac_compiler=$2 +for ac_option in --version -v -V -qversion; do + { { ac_try="$ac_compiler $ac_option >&5" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compiler $ac_option >&5") 2>conftest.err + ac_status=$? + if test -s conftest.err; then + sed '10a\ +... rest of stderr output deleted ... + 10q' conftest.err >conftest.er1 + cat conftest.er1 >&5 + fi + rm -f conftest.er1 conftest.err + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } +done + +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C++ compiler works" >&5 +$as_echo_n "checking whether the C++ compiler works... " >&6; } +ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` + +# The possible output files: +ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*" + +ac_rmfiles= +for ac_file in $ac_files +do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + * ) ac_rmfiles="$ac_rmfiles $ac_file";; + esac +done +rm -f $ac_rmfiles + +if { { ac_try="$ac_link_default" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link_default") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # Autoconf-2.13 could set the ac_cv_exeext variable to `no'. +# So ignore a value of `no', otherwise this would lead to `EXEEXT = no' +# in a Makefile. We should not override ac_cv_exeext if it was cached, +# so that the user can short-circuit this test for compilers unknown to +# Autoconf. +for ac_file in $ac_files '' +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no; + then :; else + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + fi + # We set ac_cv_exeext here because the later test for it is not + # safe: cross compilers may not add the suffix if given an `-o' + # argument, so we may need to know it at that point already. + # Even if this section looks crufty: it has the advantage of + # actually working. + break;; + * ) + break;; + esac +done +test "$ac_cv_exeext" = no && ac_cv_exeext= + +else + ac_file='' +fi +if test -z "$ac_file"; then : + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +$as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error 77 "C++ compiler cannot create executables +See \`config.log' for more details" "$LINENO" 5; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C++ compiler default output file name" >&5 +$as_echo_n "checking for C++ compiler default output file name... " >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5 +$as_echo "$ac_file" >&6; } +ac_exeext=$ac_cv_exeext + +rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5 +$as_echo_n "checking for suffix of executables... " >&6; } +if { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + break;; + * ) break;; + esac +done +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest conftest$ac_cv_exeext +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5 +$as_echo "$ac_cv_exeext" >&6; } + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +FILE *f = fopen ("conftest.out", "w"); + return ferror (f) || fclose (f) != 0; + + ; + return 0; +} +_ACEOF +ac_clean_files="$ac_clean_files conftest.out" +# Check that the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5 +$as_echo_n "checking whether we are cross compiling... " >&6; } +if test "$cross_compiling" != yes; then + { { ac_try="$ac_link" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_link") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; } + if { ac_try='./conftest$ac_cv_exeext' + { { case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_try") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot run C++ compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details" "$LINENO" 5; } + fi + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5 +$as_echo "$cross_compiling" >&6; } + +rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out +ac_clean_files=$ac_clean_files_save +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5 +$as_echo_n "checking for suffix of object files... " >&6; } +if ${ac_cv_objext+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { { ac_try="$ac_compile" +case "(($ac_try" in + *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;; + *) ac_try_echo=$ac_try;; +esac +eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\"" +$as_echo "$ac_try_echo"; } >&5 + (eval "$ac_compile") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then : + for ac_file in conftest.o conftest.obj conftest.*; do + test -f "$ac_file" || continue; + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + $as_echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "cannot compute suffix of object files: cannot compile +See \`config.log' for more details" "$LINENO" 5; } +fi +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5 +$as_echo "$ac_cv_objext" >&6; } +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C++ compiler" >&5 +$as_echo_n "checking whether we are using the GNU C++ compiler... " >&6; } +if ${ac_cv_cxx_compiler_gnu+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_compiler_gnu=yes +else + ac_compiler_gnu=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_cxx_compiler_gnu" >&5 +$as_echo "$ac_cv_cxx_compiler_gnu" >&6; } +if test $ac_compiler_gnu = yes; then + GXX=yes +else + GXX= +fi +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CXX accepts -g" >&5 +$as_echo_n "checking whether $CXX accepts -g... " >&6; } +if ${ac_cv_prog_cxx_g+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_cxx_werror_flag=$ac_cxx_werror_flag + ac_cxx_werror_flag=yes + ac_cv_prog_cxx_g=no + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +else + CXXFLAGS="" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +else + ac_cxx_werror_flag=$ac_save_cxx_werror_flag + CXXFLAGS="-g" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_prog_cxx_g=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_cxx_werror_flag=$ac_save_cxx_werror_flag +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cxx_g" >&5 +$as_echo "$ac_cv_prog_cxx_g" >&6; } +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 +$as_echo_n "checking for a sed that does not truncate output... " >&6; } +if ${ac_cv_path_SED+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_script=s/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb/ + for ac_i in 1 2 3 4 5 6 7; do + ac_script="$ac_script$as_nl$ac_script" + done + echo "$ac_script" 2>/dev/null | sed 99q >conftest.sed + { ac_script=; unset ac_script;} + if test -z "$SED"; then + ac_path_SED_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_SED="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_SED" || continue +# Check for GNU ac_path_SED and select it if it is found. + # Check for GNU $ac_path_SED +case `"$ac_path_SED" --version 2>&1` in +*GNU*) + ac_cv_path_SED="$ac_path_SED" ac_path_SED_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo '' >> "conftest.nl" + "$ac_path_SED" -f conftest.sed < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_SED_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_SED="$ac_path_SED" + ac_path_SED_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_SED_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_SED"; then + as_fn_error $? "no acceptable sed could be found in \$PATH" "$LINENO" 5 + fi +else + ac_cv_path_SED=$SED +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_SED" >&5 +$as_echo "$ac_cv_path_SED" >&6; } + SED="$ac_cv_path_SED" + rm -f conftest.sed + + +# Checks for octave depreciated symbols +## Simple symbol alternatives of different Octave versions. +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + +save_altsyms_CXX="$CXX" +save_altsyms_CXXFLAGS="$CXXFLAGS" +save_altsyms_CPPFLAGS="$CPPFLAGS" +save_altsyms_LDFLAGS="$LDFLAGS" +save_altsyms_LIBS="$LIBS" +OCTINCLUDEDIR=${OCTINCLUDEDIR:-`$MKOCTFILE -p INCFLAGS`} +OCTLIBDIR=${OCTLIBDIR:-`$MKOCTFILE -p OCTLIBDIR`} +CXX=`${MKOCTFILE} -p CXX` +CPPFLAGS="$OCTINCLUDEDIR $CPPFLAGS" +LDFLAGS="-L$OCTLIBDIR $LDFLAGS" +LIBS="-loctinterp $LIBS" + + + + +echo '/* generated by configure */' > oct-alt-includes.h + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking gripe_nonconformant or octave::err_nonconformant" >&5 +$as_echo_n "checking gripe_nonconformant or octave::err_nonconformant... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +octave::err_nonconformant ("a",0,0) + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +$as_echo "#define OCTAVE__ERR_NONCONFORMANT octave::err_nonconformant" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: octave::err_nonconformant" >&5 +$as_echo "octave::err_nonconformant" >&6; } + echo '#include +' >> oct-alt-includes.h +else + +$as_echo "#define OCTAVE__ERR_NONCONFORMANT gripe_nonconformant" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: gripe_nonconformant" >&5 +$as_echo " gripe_nonconformant" >&6; } + echo '#include ' >> oct-alt-includes.h + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking gripe_wrong_type_arg or err_wrong_type_arg" >&5 +$as_echo_n "checking gripe_wrong_type_arg or err_wrong_type_arg... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +err_wrong_type_arg ("a", "b") + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +$as_echo "#define OCTAVE__ERR_WRONG_TYPE_ARG err_wrong_type_arg" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: err_wrong_type_arg" >&5 +$as_echo "err_wrong_type_arg" >&6; } + echo '#include +' >> oct-alt-includes.h +else + +$as_echo "#define OCTAVE__ERR_WRONG_TYPE_ARG gripe_wrong_type_arg" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: gripe_wrong_type_arg" >&5 +$as_echo " gripe_wrong_type_arg" >&6; } + echo '#include ' >> oct-alt-includes.h + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking gripe_square_matrix_required or err_square_matrix_required" >&5 +$as_echo_n "checking gripe_square_matrix_required or err_square_matrix_required... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +err_square_matrix_required ("a", "b") + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +$as_echo "#define DELOCTAVE__ERR_SQUARE_MATRIX_REQUIRED err_square_matrix_required" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: err_square_matrix_required" >&5 +$as_echo "err_square_matrix_required" >&6; } + echo '#include +' >> oct-alt-includes.h +else + +$as_echo "#define DELOCTAVE__ERR_SQUARE_MATRIX_REQUIRED gripe_square_matrix_required" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: gripe_square_matrix_required" >&5 +$as_echo " gripe_square_matrix_required" >&6; } + echo '#include ' >> oct-alt-includes.h + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking gripe_invalid_conversion or err_invalid_conversion" >&5 +$as_echo_n "checking gripe_invalid_conversion or err_invalid_conversion... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +err_invalid_conversion ("a", "b") + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +$as_echo "#define OCTAVE__ERR_INVALID_CONVERSION err_invalid_conversion" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: err_invalid_conversion" >&5 +$as_echo "err_invalid_conversion" >&6; } + echo '#include +' >> oct-alt-includes.h +else + +$as_echo "#define OCTAVE__ERR_INVALID_CONVERSION gripe_invalid_conversion" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: gripe_invalid_conversion" >&5 +$as_echo " gripe_invalid_conversion" >&6; } + echo '#include ' >> oct-alt-includes.h + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking gripe_implicit_conversion or warn_implicit_conversion" >&5 +$as_echo_n "checking gripe_implicit_conversion or warn_implicit_conversion... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include + +int +main () +{ +warn_implicit_conversion ("a", "b", "c") + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +$as_echo "#define OCTAVE__WARN_INVALID_CONVERSION warn_implicit_conversion" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: warn_implicit_conversion" >&5 +$as_echo "warn_implicit_conversion" >&6; } + echo '#include +' >> oct-alt-includes.h +else + +$as_echo "#define OCTAVE__WARN_INVALID_CONVERSION gripe_implicit_conversion" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: gripe_implicit_conversion" >&5 +$as_echo " gripe_implicit_conversion" >&6; } + echo '#include ' >> oct-alt-includes.h + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking flush_octave_stdout or octave::flush_stdout" >&5 +$as_echo_n "checking flush_octave_stdout or octave::flush_stdout... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + + +int +main () +{ +octave::flush_stdout (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +$as_echo "#define OCTAVE__FLUSH_STDOUT octave::flush_stdout" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: octave::flush_stdout" >&5 +$as_echo "octave::flush_stdout" >&6; } + echo ' +' >> oct-alt-includes.h +else + +$as_echo "#define OCTAVE__FLUSH_STDOUT flush_octave_stdout" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: flush_octave_stdout" >&5 +$as_echo " flush_octave_stdout" >&6; } + echo '' >> oct-alt-includes.h + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking is_complex_type or iscomplex" >&5 +$as_echo_n "checking is_complex_type or iscomplex... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + + +int +main () +{ +octave_value ().iscomplex (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +$as_echo "#define OV_ISCOMPLEX iscomplex" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: iscomplex" >&5 +$as_echo "iscomplex" >&6; } + echo ' +' >> oct-alt-includes.h +else + +$as_echo "#define OV_ISCOMPLEX is_complex_type" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: is_complex_type" >&5 +$as_echo " is_complex_type" >&6; } + echo '' >> oct-alt-includes.h + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking is_real_type or isreal" >&5 +$as_echo_n "checking is_real_type or isreal... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + + +int +main () +{ +octave_value ().isreal (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +$as_echo "#define OV_ISREAL isreal" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: isreal" >&5 +$as_echo "isreal" >&6; } + echo ' +' >> oct-alt-includes.h +else + +$as_echo "#define OV_ISREAL is_real_type" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: is_real_type" >&5 +$as_echo " is_real_type" >&6; } + echo '' >> oct-alt-includes.h + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking is_numeric_type or isnumeric" >&5 +$as_echo_n "checking is_numeric_type or isnumeric... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + + +int +main () +{ +octave_value ().isnumeric (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +$as_echo "#define OV_ISNUMERIC isnumeric" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: isnumeric" >&5 +$as_echo "isnumeric" >&6; } + echo ' +' >> oct-alt-includes.h +else + +$as_echo "#define OV_ISNUMERIC is_numeric_type" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: is_numeric_type" >&5 +$as_echo " is_numeric_type" >&6; } + echo '' >> oct-alt-includes.h + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking is_empty or isempty" >&5 +$as_echo_n "checking is_empty or isempty... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + + +int +main () +{ +octave_value ().isempty (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +$as_echo "#define OV_ISEMPTY isempty" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: isempty" >&5 +$as_echo "isempty" >&6; } + echo ' +' >> oct-alt-includes.h +else + +$as_echo "#define OV_ISEMPTY is_empty" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: is_empty" >&5 +$as_echo " is_empty" >&6; } + echo '' >> oct-alt-includes.h + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking oct_mach_info::float_format or octave::mach_info::float_format" >&5 +$as_echo_n "checking oct_mach_info::float_format or octave::mach_info::float_format... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + + + + +int +main () +{ +octave::mach_info::float_format fmt; + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + +$as_echo "#define OCTAVE_MACH_INFO_FLOAT_FORMAT octave::mach_info::float_format" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: octave::mach_info::float_format" >&5 +$as_echo "octave::mach_info::float_format" >&6; } + echo ' + + +' >> oct-alt-includes.h +else + +$as_echo "#define OCTAVE_MACH_INFO_FLOAT_FORMAT oct_mach_info::float_format" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: oct_mach_info::float_format" >&5 +$as_echo " oct_mach_info::float_format" >&6; } + echo '' >> oct-alt-includes.h + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + + + + + + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C++ preprocessor" >&5 +$as_echo_n "checking how to run the C++ preprocessor... " >&6; } +if test -z "$CXXCPP"; then + if ${ac_cv_prog_CXXCPP+:} false; then : + $as_echo_n "(cached) " >&6 +else + # Double quotes because CXXCPP needs to be expanded + for CXXCPP in "$CXX -E" "/lib/cpp" + do + ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + break +fi + + done + ac_cv_prog_CXXCPP=$CXXCPP + +fi + CXXCPP=$ac_cv_prog_CXXCPP +else + ac_cv_prog_CXXCPP=$CXXCPP +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CXXCPP" >&5 +$as_echo "$CXXCPP" >&6; } +ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer to if __STDC__ is defined, since + # exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#ifdef __STDC__ +# include +#else +# include +#endif + Syntax error +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + +else + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.i conftest.$ac_ext + + # OK, works on sane cases. Now check whether nonexistent headers + # can be detected and how. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +_ACEOF +if ac_fn_cxx_try_cpp "$LINENO"; then : + # Broken: success on invalid input. +continue +else + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.i conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.i conftest.err conftest.$ac_ext +if $ac_preproc_ok; then : + +else + { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5 +$as_echo "$as_me: error: in \`$ac_pwd':" >&2;} +as_fn_error $? "C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details" "$LINENO" 5; } +fi + +ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5 +$as_echo_n "checking for grep that handles long lines and -e... " >&6; } +if ${ac_cv_path_GREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -z "$GREP"; then + ac_path_GREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in grep ggrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_GREP" || continue +# Check for GNU ac_path_GREP and select it if it is found. + # Check for GNU $ac_path_GREP +case `"$ac_path_GREP" --version 2>&1` in +*GNU*) + ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'GREP' >> "conftest.nl" + "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_GREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_GREP="$ac_path_GREP" + ac_path_GREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_GREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_GREP"; then + as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_GREP=$GREP +fi + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5 +$as_echo "$ac_cv_path_GREP" >&6; } + GREP="$ac_cv_path_GREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5 +$as_echo_n "checking for egrep... " >&6; } +if ${ac_cv_path_EGREP+:} false; then : + $as_echo_n "(cached) " >&6 +else + if echo a | $GREP -E '(a|b)' >/dev/null 2>&1 + then ac_cv_path_EGREP="$GREP -E" + else + if test -z "$EGREP"; then + ac_path_EGREP_found=false + # Loop through the user's path and test for each of PROGNAME-LIST + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_prog in egrep; do + for ac_exec_ext in '' $ac_executable_extensions; do + ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext" + as_fn_executable_p "$ac_path_EGREP" || continue +# Check for GNU ac_path_EGREP and select it if it is found. + # Check for GNU $ac_path_EGREP +case `"$ac_path_EGREP" --version 2>&1` in +*GNU*) + ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;; +*) + ac_count=0 + $as_echo_n 0123456789 >"conftest.in" + while : + do + cat "conftest.in" "conftest.in" >"conftest.tmp" + mv "conftest.tmp" "conftest.in" + cp "conftest.in" "conftest.nl" + $as_echo 'EGREP' >> "conftest.nl" + "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break + diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break + as_fn_arith $ac_count + 1 && ac_count=$as_val + if test $ac_count -gt ${ac_path_EGREP_max-0}; then + # Best one so far, save it but keep looking for a better one + ac_cv_path_EGREP="$ac_path_EGREP" + ac_path_EGREP_max=$ac_count + fi + # 10*(2^10) chars as input seems more than enough + test $ac_count -gt 10 && break + done + rm -f conftest.in conftest.tmp conftest.nl conftest.out;; +esac + + $ac_path_EGREP_found && break 3 + done + done + done +IFS=$as_save_IFS + if test -z "$ac_cv_path_EGREP"; then + as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5 + fi +else + ac_cv_path_EGREP=$EGREP +fi + + fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5 +$as_echo "$ac_cv_path_EGREP" >&6; } + EGREP="$ac_cv_path_EGREP" + + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5 +$as_echo_n "checking for ANSI C header files... " >&6; } +if ${ac_cv_header_stdc+:} false; then : + $as_echo_n "(cached) " >&6 +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#include +#include + +int +main () +{ + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + ac_cv_header_stdc=yes +else + ac_cv_header_stdc=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then : + +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then : + : +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + return 2; + return 0; +} +_ACEOF +if ac_fn_cxx_try_run "$LINENO"; then : + +else + ac_cv_header_stdc=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5 +$as_echo "$ac_cv_header_stdc" >&6; } +if test $ac_cv_header_stdc = yes; then + +$as_echo "#define STDC_HEADERS 1" >>confdefs.h + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do : + as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` +ac_fn_cxx_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default +" +if eval test \"x\$"$as_ac_Header"\" = x"yes"; then : + cat >>confdefs.h <<_ACEOF +#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +for ac_header in octave/oct.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "octave/oct.h" "ac_cv_header_octave_oct_h" "$ac_includes_default" +if test "x$ac_cv_header_octave_oct_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OCTAVE_OCT_H 1 +_ACEOF + +fi + +done + +for ac_header in octave/base-lu.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "octave/base-lu.h" "ac_cv_header_octave_base_lu_h" "$ac_includes_default" +if test "x$ac_cv_header_octave_base_lu_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OCTAVE_BASE_LU_H 1 +_ACEOF + +fi + +done + +for ac_header in octave/lu.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "octave/lu.h" "ac_cv_header_octave_lu_h" "$ac_includes_default" +if test "x$ac_cv_header_octave_lu_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OCTAVE_LU_H 1 +_ACEOF + +fi + +done + +for ac_header in octave/gripes.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "octave/gripes.h" "ac_cv_header_octave_gripes_h" "$ac_includes_default" +if test "x$ac_cv_header_octave_gripes_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OCTAVE_GRIPES_H 1 +_ACEOF + +fi + +done + +for ac_header in octave/errwarn.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "octave/errwarn.h" "ac_cv_header_octave_errwarn_h" "$ac_includes_default" +if test "x$ac_cv_header_octave_errwarn_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OCTAVE_ERRWARN_H 1 +_ACEOF + +fi + +done + +for ac_header in octave/ovl.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "octave/ovl.h" "ac_cv_header_octave_ovl_h" "$ac_includes_default" +if test "x$ac_cv_header_octave_ovl_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OCTAVE_OVL_H 1 +_ACEOF + +fi + +done + +for ac_header in octave/oct-obj.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "octave/oct-obj.h" "ac_cv_header_octave_oct_obj_h" "$ac_includes_default" +if test "x$ac_cv_header_octave_oct_obj_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OCTAVE_OCT_OBJ_H 1 +_ACEOF + +fi + +done + +for ac_header in octave/ls-oct-ascii.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "octave/ls-oct-ascii.h" "ac_cv_header_octave_ls_oct_ascii_h" "$ac_includes_default" +if test "x$ac_cv_header_octave_ls_oct_ascii_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OCTAVE_LS_OCT_ASCII_H 1 +_ACEOF + +fi + +done + +for ac_header in octave/ls-oct-text.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "octave/ls-oct-text.h" "ac_cv_header_octave_ls_oct_text_h" "$ac_includes_default" +if test "x$ac_cv_header_octave_ls_oct_text_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OCTAVE_LS_OCT_TEXT_H 1 +_ACEOF + +fi + +done + +for ac_header in octave/oct-obj.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "octave/oct-obj.h" "ac_cv_header_octave_oct_obj_h" "$ac_includes_default" +if test "x$ac_cv_header_octave_oct_obj_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OCTAVE_OCT_OBJ_H 1 +_ACEOF + +fi + +done + +for ac_header in octave/interpreter.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "octave/interpreter.h" "ac_cv_header_octave_interpreter_h" "$ac_includes_default" +if test "x$ac_cv_header_octave_interpreter_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_OCTAVE_INTERPRETER_H 1 +_ACEOF + +fi + +done + + +CXX=$save_altsyms_CXX +CXXFLAGS=$save_altsyms_CXXFLAGS +CPPFLAGS=$save_altsyms_CPPFLAGS +LDFLAGS=$save_altsyms_LDFLAGS +LIBS=$save_altsyms_LIBS + +have_hdf5=no +# check for HDF5 using pkg-config + + + + + + + +if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}pkg-config", so it can be a program name with args. +set dummy ${ac_tool_prefix}pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_PKG_CONFIG="$PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +PKG_CONFIG=$ac_cv_path_PKG_CONFIG +if test -n "$PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $PKG_CONFIG" >&5 +$as_echo "$PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + +fi +if test -z "$ac_cv_path_PKG_CONFIG"; then + ac_pt_PKG_CONFIG=$PKG_CONFIG + # Extract the first word of "pkg-config", so it can be a program name with args. +set dummy pkg-config; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_ac_pt_PKG_CONFIG+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $ac_pt_PKG_CONFIG in + [\\/]* | ?:[\\/]*) + ac_cv_path_ac_pt_PKG_CONFIG="$ac_pt_PKG_CONFIG" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_ac_pt_PKG_CONFIG="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +ac_pt_PKG_CONFIG=$ac_cv_path_ac_pt_PKG_CONFIG +if test -n "$ac_pt_PKG_CONFIG"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pt_PKG_CONFIG" >&5 +$as_echo "$ac_pt_PKG_CONFIG" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + if test "x$ac_pt_PKG_CONFIG" = x; then + PKG_CONFIG="" + else + case $cross_compiling:$ac_tool_warned in +yes:) +{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5 +$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;} +ac_tool_warned=yes ;; +esac + PKG_CONFIG=$ac_pt_PKG_CONFIG + fi +else + PKG_CONFIG="$ac_cv_path_PKG_CONFIG" +fi + +fi +if test -n "$PKG_CONFIG"; then + _pkg_min_version=0.9.0 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking pkg-config is at least version $_pkg_min_version" >&5 +$as_echo_n "checking pkg-config is at least version $_pkg_min_version... " >&6; } + if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + PKG_CONFIG="" + fi +fi + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for HDF5" >&5 +$as_echo_n "checking for HDF5... " >&6; } + +if test -n "$HDF5_CFLAGS"; then + pkg_cv_HDF5_CFLAGS="$HDF5_CFLAGS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"hdf5\""; } >&5 + ($PKG_CONFIG --exists --print-errors "hdf5") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_HDF5_CFLAGS=`$PKG_CONFIG --cflags "hdf5" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi +if test -n "$HDF5_LIBS"; then + pkg_cv_HDF5_LIBS="$HDF5_LIBS" + elif test -n "$PKG_CONFIG"; then + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"hdf5\""; } >&5 + ($PKG_CONFIG --exists --print-errors "hdf5") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_HDF5_LIBS=`$PKG_CONFIG --libs "hdf5" 2>/dev/null` + test "x$?" != "x0" && pkg_failed=yes +else + pkg_failed=yes +fi + else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + HDF5_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "hdf5" 2>&1` + else + HDF5_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "hdf5" 2>&1` + fi + # Put the nasty error message in config.log where it belongs + echo "$HDF5_PKG_ERRORS" >&5 + + + +elif test $pkg_failed = untried; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + +else + HDF5_CFLAGS=$pkg_cv_HDF5_CFLAGS + HDF5_LIBS=$pkg_cv_HDF5_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + have_hdf5=yes +fi +if test $have_hdf5 = no; then + save_CPPFLAGS="$CPPFLAGS" + save_LIBS="$LIBS" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for H5Fopen in -lhdf5" >&5 +$as_echo_n "checking for H5Fopen in -lhdf5... " >&6; } +if ${ac_cv_lib_hdf5_H5Fopen+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lhdf5 $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char H5Fopen (); +int +main () +{ +return H5Fopen (); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_link "$LINENO"; then : + ac_cv_lib_hdf5_H5Fopen=yes +else + ac_cv_lib_hdf5_H5Fopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_hdf5_H5Fopen" >&5 +$as_echo "$ac_cv_lib_hdf5_H5Fopen" >&6; } +if test "x$ac_cv_lib_hdf5_H5Fopen" = xyes; then : + + have_hdf5=yes + for ac_header in hdf5.h +do : + ac_fn_cxx_check_header_mongrel "$LINENO" "hdf5.h" "ac_cv_header_hdf5_h" "$ac_includes_default" +if test "x$ac_cv_header_hdf5_h" = xyes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_HDF5_H 1 +_ACEOF + +fi + +done + + HDF5_LIBS=-lhdf5 + +fi + + CPPFLAGS="$save_CPPFLAGS" + LIBS="$save_LIBS" +fi +if test $have_hdf5 = no; then + as_fn_error $? "hdf5 not found" "$LINENO" 5 +fi + +comm_OCT_EVAL="$OCTAVE --norc --no-history --silent --eval" + +comm_CXXFLAGS=`$MKOCTFILE -p ALL_CXXFLAGS` + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for octave_hdf5_id type" >&5 +$as_echo_n "checking for octave_hdf5_id type... " >&6; } +if ${comm_cv_octave_hdf5_id_type+:} false; then : + $as_echo_n "(cached) " >&6 +else + comm_save_CPPFLAGS=$CPPFLAGS + comm_save_CXXFLAGS=$CXXFLAGS + CPPFLAGS="$CPPFLAGS $HDF5_CFLAGS" + CXXFLAGS="$CXXFLAGS $comm_CXXFLAGS" + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #include + +int +main () +{ + + octave_hdf5_id x; + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + comm_cv_octave_hdf5_id_type=yes +else + comm_cv_octave_hdf5_id_type=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + CPPFLAGS=$comm_save_CPPFLAGS + CXXFLAGS=$comm_save_CXXFLAGS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $comm_cv_octave_hdf5_id_type" >&5 +$as_echo "$comm_cv_octave_hdf5_id_type" >&6; } +if test $comm_cv_octave_hdf5_id_type = yes; then + +$as_echo "#define HAVE_OCTAVE_HDF5_ID_TYPE 1" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for octave_base_value::gripe_load and octave_base_value::gripe_save" >&5 +$as_echo_n "checking for octave_base_value::gripe_load and octave_base_value::gripe_save... " >&6; } +if ${comm_cv_octave_base_value_gripe_load_save+:} false; then : + $as_echo_n "(cached) " >&6 +else + comm_save_CPPFLAGS=$CPPFLAGS + comm_save_CXXFLAGS=$CXXFLAGS + CPPFLAGS="$CPPFLAGS $HDF5_CFLAGS" + CXXFLAGS="$CXXFLAGS $comm_CXXFLAGS" + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #include + class foo : public octave_base_value + { + public: + foo () {} + void func () { gripe_load ("func"); gripe_save ("func"); } + }; + +int +main () +{ + + foo x; + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + comm_cv_octave_base_value_gripe_load_save=yes +else + comm_cv_octave_base_value_gripe_load_save=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + CPPFLAGS=$comm_save_CPPFLAGS + CXXFLAGS=$comm_save_CXXFLAGS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $comm_cv_octave_base_value_gripe_load_save" >&5 +$as_echo "$comm_cv_octave_base_value_gripe_load_save" >&6; } +if test $comm_cv_octave_base_value_gripe_load_save = yes; then + +$as_echo "#define HAVE_OCTAVE_BASE_VALUE_GRIPE_LOAD_SAVE 1" >>confdefs.h + +fi + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether octave_base_value::print is const-qualified" >&5 +$as_echo_n "checking whether octave_base_value::print is const-qualified... " >&6; } +if ${comm_cv_octave_base_value_print_const_qualified+:} false; then : + $as_echo_n "(cached) " >&6 +else + comm_save_CPPFLAGS=$CPPFLAGS + comm_save_CXXFLAGS=$CXXFLAGS + CPPFLAGS="$CPPFLAGS $HDF5_CFLAGS" + CXXFLAGS="$CXXFLAGS $comm_CXXFLAGS" + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + #include + #include + #include + +int +main () +{ + + const octave_base_value x; x.print (std::cout); + + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + comm_cv_octave_base_value_print_const_qualified=yes +else + comm_cv_octave_base_value_print_const_qualified=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + CPPFLAGS=$comm_save_CPPFLAGS + CXXFLAGS=$comm_save_CXXFLAGS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $comm_cv_octave_base_value_print_const_qualified" >&5 +$as_echo "$comm_cv_octave_base_value_print_const_qualified" >&6; } +if test $comm_cv_octave_base_value_print_const_qualified = yes; then + +$as_echo "#define HAVE_OCTAVE_BASE_VALUE_PRINT_CONST 1" >>confdefs.h + +fi + +ac_config_files="$ac_config_files Makefile" + +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, we kill variables containing newlines. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +( + for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do + eval ac_val=\$$ac_var + case $ac_val in #( + *${as_nl}*) + case $ac_var in #( + *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5 +$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;; + esac + case $ac_var in #( + _ | IFS | as_nl) ;; #( + BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #( + *) { eval $ac_var=; unset $ac_var;} ;; + esac ;; + esac + done + + (set) 2>&1 | + case $as_nl`(ac_space=' '; set) 2>&1` in #( + *${as_nl}ac_space=\ *) + # `set' does not quote correctly, so add quotes: double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \. + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; #( + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p" + ;; + esac | + sort +) | + sed ' + /^ac_cv_env_/b end + t clear + :clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + :end' >>confcache +if diff "$cache_file" confcache >/dev/null 2>&1; then :; else + if test -w "$cache_file"; then + if test "x$cache_file" != "x/dev/null"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5 +$as_echo "$as_me: updating cache $cache_file" >&6;} + if test ! -f "$cache_file" || test -h "$cache_file"; then + cat confcache >"$cache_file" + else + case $cache_file in #( + */* | ?:*) + mv -f confcache "$cache_file"$$ && + mv -f "$cache_file"$$ "$cache_file" ;; #( + *) + mv -f confcache "$cache_file" ;; + esac + fi + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5 +$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;} + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +U= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_script='s/\$U\././;s/\.o$//;s/\.obj$//' + ac_i=`$as_echo "$ac_i" | sed "$ac_script"` + # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR + # will be set to the directory where LIBOBJS objects are built. + as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext" + as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + + +: "${CONFIG_STATUS=./config.status}" +ac_write_fail=0 +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5 +$as_echo "$as_me: creating $CONFIG_STATUS" >&6;} +as_write_fail=0 +cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1 +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false + +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1 +## -------------------- ## +## M4sh Initialization. ## +## -------------------- ## + +# Be more Bourne compatible +DUALCASE=1; export DUALCASE # for MKS sh +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then : + emulate sh + NULLCMD=: + # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' + setopt NO_GLOB_SUBST +else + case `(set -o) 2>/dev/null` in #( + *posix*) : + set -o posix ;; #( + *) : + ;; +esac +fi + + +as_nl=' +' +export as_nl +# Printing a long string crashes Solaris 7 /usr/bin/printf. +as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo +as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo +# Prefer a ksh shell builtin over an external printf program on Solaris, +# but without wasting forks for bash or zsh. +if test -z "$BASH_VERSION$ZSH_VERSION" \ + && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='print -r --' + as_echo_n='print -rn --' +elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then + as_echo='printf %s\n' + as_echo_n='printf %s' +else + if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then + as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"' + as_echo_n='/usr/ucb/echo -n' + else + as_echo_body='eval expr "X$1" : "X\\(.*\\)"' + as_echo_n_body='eval + arg=$1; + case $arg in #( + *"$as_nl"*) + expr "X$arg" : "X\\(.*\\)$as_nl"; + arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;; + esac; + expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl" + ' + export as_echo_n_body + as_echo_n='sh -c $as_echo_n_body as_echo' + fi + export as_echo_body + as_echo='sh -c $as_echo_body as_echo' +fi + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + PATH_SEPARATOR=: + (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && { + (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 || + PATH_SEPARATOR=';' + } +fi + + +# IFS +# We need space, tab and new line, in precisely that order. Quoting is +# there to prevent editors from complaining about space-tab. +# (If _AS_PATH_WALK were called with IFS unset, it would disable word +# splitting by setting IFS to empty value.) +IFS=" "" $as_nl" + +# Find who we are. Look in the path if we contain no directory separator. +as_myself= +case $0 in #(( + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break + done +IFS=$as_save_IFS + + ;; +esac +# We did not find ourselves, most probably we were run as `sh COMMAND' +# in which case we are not to be found in the path. +if test "x$as_myself" = x; then + as_myself=$0 +fi +if test ! -f "$as_myself"; then + $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2 + exit 1 +fi + +# Unset variables that we do not need and which cause bugs (e.g. in +# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1" +# suppresses any "Segmentation fault" message there. '((' could +# trigger a bug in pdksh 5.2.14. +for as_var in BASH_ENV ENV MAIL MAILPATH +do eval test x\${$as_var+set} = xset \ + && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || : +done +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +LC_ALL=C +export LC_ALL +LANGUAGE=C +export LANGUAGE + +# CDPATH. +(unset CDPATH) >/dev/null 2>&1 && unset CDPATH + + +# as_fn_error STATUS ERROR [LINENO LOG_FD] +# ---------------------------------------- +# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are +# provided, also output the error to LOG_FD, referencing LINENO. Then exit the +# script with STATUS, using 1 if that was 0. +as_fn_error () +{ + as_status=$1; test $as_status -eq 0 && as_status=1 + if test "$4"; then + as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack + $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4 + fi + $as_echo "$as_me: error: $2" >&2 + as_fn_exit $as_status +} # as_fn_error + + +# as_fn_set_status STATUS +# ----------------------- +# Set $? to STATUS, without forking. +as_fn_set_status () +{ + return $1 +} # as_fn_set_status + +# as_fn_exit STATUS +# ----------------- +# Exit the shell with STATUS, even in a "trap 0" or "set -e" context. +as_fn_exit () +{ + set +e + as_fn_set_status $1 + exit $1 +} # as_fn_exit + +# as_fn_unset VAR +# --------------- +# Portably unset VAR. +as_fn_unset () +{ + { eval $1=; unset $1;} +} +as_unset=as_fn_unset +# as_fn_append VAR VALUE +# ---------------------- +# Append the text in VALUE to the end of the definition contained in VAR. Take +# advantage of any shell optimizations that allow amortized linear growth over +# repeated appends, instead of the typical quadratic growth present in naive +# implementations. +if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then : + eval 'as_fn_append () + { + eval $1+=\$2 + }' +else + as_fn_append () + { + eval $1=\$$1\$2 + } +fi # as_fn_append + +# as_fn_arith ARG... +# ------------------ +# Perform arithmetic evaluation on the ARGs, and store the result in the +# global $as_val. Take advantage of shells that can avoid forks. The arguments +# must be portable across $(()) and expr. +if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then : + eval 'as_fn_arith () + { + as_val=$(( $* )) + }' +else + as_fn_arith () + { + as_val=`expr "$@" || test $? -eq 1` + } +fi # as_fn_arith + + +if expr a : '\(a\)' >/dev/null 2>&1 && + test "X`expr 00001 : '.*\(...\)'`" = X001; then + as_expr=expr +else + as_expr=false +fi + +if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + +if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then + as_dirname=dirname +else + as_dirname=false +fi + +as_me=`$as_basename -- "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ + s//\1/ + q + } + /^X\/\(\/\/\)$/{ + s//\1/ + q + } + /^X\/\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +ECHO_C= ECHO_N= ECHO_T= +case `echo -n x` in #((((( +-n*) + case `echo 'xy\c'` in + *c*) ECHO_T=' ';; # ECHO_T is single tab character. + xy) ECHO_C='\c';; + *) echo `echo ksh88 bug on AIX 6.1` > /dev/null + ECHO_T=' ';; + esac;; +*) + ECHO_N='-n';; +esac + +rm -f conf$$ conf$$.exe conf$$.file +if test -d conf$$.dir; then + rm -f conf$$.dir/conf$$.file +else + rm -f conf$$.dir + mkdir conf$$.dir 2>/dev/null +fi +if (echo >conf$$.file) 2>/dev/null; then + if ln -s conf$$.file conf$$ 2>/dev/null; then + as_ln_s='ln -s' + # ... but there are two gotchas: + # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail. + # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable. + # In both cases, we have to default to `cp -pR'. + ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe || + as_ln_s='cp -pR' + elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln + else + as_ln_s='cp -pR' + fi +else + as_ln_s='cp -pR' +fi +rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file +rmdir conf$$.dir 2>/dev/null + + +# as_fn_mkdir_p +# ------------- +# Create "$as_dir" as a directory, including parents if necessary. +as_fn_mkdir_p () +{ + + case $as_dir in #( + -*) as_dir=./$as_dir;; + esac + test -d "$as_dir" || eval $as_mkdir_p || { + as_dirs= + while :; do + case $as_dir in #( + *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'( + *) as_qdir=$as_dir;; + esac + as_dirs="'$as_qdir' $as_dirs" + as_dir=`$as_dirname -- "$as_dir" || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + test -d "$as_dir" && break + done + test -z "$as_dirs" || eval "mkdir $as_dirs" + } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir" + + +} # as_fn_mkdir_p +if mkdir -p . 2>/dev/null; then + as_mkdir_p='mkdir -p "$as_dir"' +else + test -d ./-p && rmdir ./-p + as_mkdir_p=false +fi + + +# as_fn_executable_p FILE +# ----------------------- +# Test if FILE is an executable regular file. +as_fn_executable_p () +{ + test -f "$1" && test -x "$1" +} # as_fn_executable_p +as_test_x='test -x' +as_executable_p=as_fn_executable_p + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" + + +exec 6>&1 +## ----------------------------------- ## +## Main body of $CONFIG_STATUS script. ## +## ----------------------------------- ## +_ASEOF +test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# Save the log message, to keep $0 and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. +ac_log=" +This file was extended by Octave-Forge communications package $as_me 0, which was +generated by GNU Autoconf 2.69. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +on `(hostname || uname -n) 2>/dev/null | sed 1q` +" + +_ACEOF + +case $ac_config_files in *" +"*) set x $ac_config_files; shift; ac_config_files=$*;; +esac + +case $ac_config_headers in *" +"*) set x $ac_config_headers; shift; ac_config_headers=$*;; +esac + + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +# Files that config.status was made for. +config_files="$ac_config_files" +config_headers="$ac_config_headers" + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +ac_cs_usage="\ +\`$as_me' instantiates files and other configuration actions +from templates according to the current configuration. Unless the files +and actions are specified as TAGs, all are instantiated by default. + +Usage: $0 [OPTION]... [TAG]... + + -h, --help print this help, then exit + -V, --version print version number and configuration settings, then exit + --config print configuration, then exit + -q, --quiet, --silent + do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Report bugs to the package provider." + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" +ac_cs_version="\\ +Octave-Forge communications package config.status 0 +configured by $0, generated by GNU Autoconf 2.69, + with options \\"\$ac_cs_config\\" + +Copyright (C) 2012 Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." + +ac_pwd='$ac_pwd' +srcdir='$srcdir' +test -n "\$AWK" || AWK=awk +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# The default lists apply if the user does not specify any file. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=?*) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'` + ac_shift=: + ;; + --*=) + ac_option=`expr "X$1" : 'X\([^=]*\)='` + ac_optarg= + ac_shift=: + ;; + *) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + esac + + case $ac_option in + # Handling of the options. + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --versio | --versi | --vers | --ver | --ve | --v | -V ) + $as_echo "$ac_cs_version"; exit ;; + --config | --confi | --conf | --con | --co | --c ) + $as_echo "$ac_cs_config"; exit ;; + --debug | --debu | --deb | --de | --d | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + '') as_fn_error $? "missing file argument" ;; + esac + as_fn_append CONFIG_FILES " '$ac_optarg'" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + case $ac_optarg in + *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + as_fn_append CONFIG_HEADERS " '$ac_optarg'" + ac_need_defaults=false;; + --he | --h) + # Conflict between --help and --header + as_fn_error $? "ambiguous option: \`$1' +Try \`$0 --help' for more information.";; + --help | --hel | -h ) + $as_echo "$ac_cs_usage"; exit ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) as_fn_error $? "unrecognized option: \`$1' +Try \`$0 --help' for more information." ;; + + *) as_fn_append ac_config_targets " $1" + ac_need_defaults=false ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +if \$ac_cs_recheck; then + set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion + shift + \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6 + CONFIG_SHELL='$SHELL' + export CONFIG_SHELL + exec "\$@" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX + $as_echo "$ac_log" +} >&5 + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + +# Handling of arguments. +for ac_config_target in $ac_config_targets +do + case $ac_config_target in + "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; + + *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;; + esac +done + + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason against having it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Hook for its removal unless debugging. +# Note that there is a small window in which the directory will not be cleaned: +# after its creation but before its name has been assigned to `$tmp'. +$debug || +{ + tmp= ac_tmp= + trap 'exit_status=$? + : "${ac_tmp:=$tmp}" + { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status +' 0 + trap 'as_fn_exit 1' 1 2 13 15 +} +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` && + test -d "$tmp" +} || +{ + tmp=./conf$$-$RANDOM + (umask 077 && mkdir "$tmp") +} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5 +ac_tmp=$tmp + +# Set up the scripts for CONFIG_FILES section. +# No need to generate them if there are no CONFIG_FILES. +# This happens for instance with `./config.status config.h'. +if test -n "$CONFIG_FILES"; then + + +ac_cr=`echo X | tr X '\015'` +# On cygwin, bash can eat \r inside `` if the user requested igncr. +# But we know of no other shell where ac_cr would be empty at this +# point, so we can use a bashism as a fallback. +if test "x$ac_cr" = x; then + eval ac_cr=\$\'\\r\' +fi +ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' /dev/null` +if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then + ac_cs_awk_cr='\\r' +else + ac_cs_awk_cr=$ac_cr +fi + +echo 'BEGIN {' >"$ac_tmp/subs1.awk" && +_ACEOF + + +{ + echo "cat >conf$$subs.awk <<_ACEOF" && + echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' && + echo "_ACEOF" +} >conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 +ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'` +ac_delim='%!_!# ' +for ac_last_try in false false false false false :; do + . ./conf$$subs.sh || + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + + ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X` + if test $ac_delim_n = $ac_delim_num; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done +rm -f conf$$subs.sh + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK && +_ACEOF +sed -n ' +h +s/^/S["/; s/!.*/"]=/ +p +g +s/^[^!]*!// +:repl +t repl +s/'"$ac_delim"'$// +t delim +:nl +h +s/\(.\{148\}\)..*/\1/ +t more1 +s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/ +p +n +b repl +:more1 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t nl +:delim +h +s/\(.\{148\}\)..*/\1/ +t more2 +s/["\\]/\\&/g; s/^/"/; s/$/"/ +p +b +:more2 +s/["\\]/\\&/g; s/^/"/; s/$/"\\/ +p +g +s/.\{148\}// +t delim +' >$CONFIG_STATUS || ac_write_fail=1 +rm -f conf$$subs.awk +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +_ACAWK +cat >>"\$ac_tmp/subs1.awk" <<_ACAWK && + for (key in S) S_is_set[key] = 1 + FS = "" + +} +{ + line = $ 0 + nfields = split(line, field, "@") + substed = 0 + len = length(field[1]) + for (i = 2; i < nfields; i++) { + key = field[i] + keylen = length(key) + if (S_is_set[key]) { + value = S[key] + line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3) + len += length(value) + length(field[++i]) + substed = 1 + } else + len += 1 + keylen + } + + print line +} + +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then + sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g" +else + cat +fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \ + || as_fn_error $? "could not setup config files machinery" "$LINENO" 5 +_ACEOF + +# VPATH may cause trouble with some makes, so we remove sole $(srcdir), +# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{ +h +s/// +s/^/:/ +s/[ ]*$/:/ +s/:\$(srcdir):/:/g +s/:\${srcdir}:/:/g +s/:@srcdir@:/:/g +s/^:*// +s/:*$// +x +s/\(=[ ]*\).*/\1/ +G +s/\n// +s/^[^=]*=[ ]*$// +}' +fi + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +fi # test -n "$CONFIG_FILES" + +# Set up the scripts for CONFIG_HEADERS section. +# No need to generate them if there are no CONFIG_HEADERS. +# This happens for instance with `./config.status Makefile'. +if test -n "$CONFIG_HEADERS"; then +cat >"$ac_tmp/defines.awk" <<\_ACAWK || +BEGIN { +_ACEOF + +# Transform confdefs.h into an awk script `defines.awk', embedded as +# here-document in config.status, that substitutes the proper values into +# config.h.in to produce config.h. + +# Create a delimiter string that does not exist in confdefs.h, to ease +# handling of long lines. +ac_delim='%!_!# ' +for ac_last_try in false false :; do + ac_tt=`sed -n "/$ac_delim/p" confdefs.h` + if test -z "$ac_tt"; then + break + elif $ac_last_try; then + as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5 + else + ac_delim="$ac_delim!$ac_delim _$ac_delim!! " + fi +done + +# For the awk script, D is an array of macro values keyed by name, +# likewise P contains macro parameters if any. Preserve backslash +# newline sequences. + +ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]* +sed -n ' +s/.\{148\}/&'"$ac_delim"'/g +t rset +:rset +s/^[ ]*#[ ]*define[ ][ ]*/ / +t def +d +:def +s/\\$// +t bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3"/p +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p +d +:bsnl +s/["\\]/\\&/g +s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\ +D["\1"]=" \3\\\\\\n"\\/p +t cont +s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p +t cont +d +:cont +n +s/.\{148\}/&'"$ac_delim"'/g +t clear +:clear +s/\\$// +t bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/"/p +d +:bsnlc +s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p +b cont +' >$CONFIG_STATUS || ac_write_fail=1 + +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + for (key in D) D_is_set[key] = 1 + FS = "" +} +/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ { + line = \$ 0 + split(line, arg, " ") + if (arg[1] == "#") { + defundef = arg[2] + mac1 = arg[3] + } else { + defundef = substr(arg[1], 2) + mac1 = arg[2] + } + split(mac1, mac2, "(") #) + macro = mac2[1] + prefix = substr(line, 1, index(line, defundef) - 1) + if (D_is_set[macro]) { + # Preserve the white space surrounding the "#". + print prefix "define", macro P[macro] D[macro] + next + } else { + # Replace #undef with comments. This is necessary, for example, + # in the case of _POSIX_SOURCE, which is predefined and required + # on some systems where configure will not decide to define it. + if (defundef == "undef") { + print "/*", prefix defundef, macro, "*/" + next + } + } +} +{ print } +_ACAWK +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 + as_fn_error $? "could not setup config headers machinery" "$LINENO" 5 +fi # test -n "$CONFIG_HEADERS" + + +eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS " +shift +for ac_tag +do + case $ac_tag in + :[FHLC]) ac_mode=$ac_tag; continue;; + esac + case $ac_mode$ac_tag in + :[FHL]*:*);; + :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;; + :[FH]-) ac_tag=-:-;; + :[FH]*) ac_tag=$ac_tag:$ac_tag.in;; + esac + ac_save_IFS=$IFS + IFS=: + set x $ac_tag + IFS=$ac_save_IFS + shift + ac_file=$1 + shift + + case $ac_mode in + :L) ac_source=$1;; + :[FH]) + ac_file_inputs= + for ac_f + do + case $ac_f in + -) ac_f="$ac_tmp/stdin";; + *) # Look for the file first in the build tree, then in the source tree + # (if the path is not absolute). The absolute path cannot be DOS-style, + # because $ac_f cannot contain `:'. + test -f "$ac_f" || + case $ac_f in + [\\/$]*) false;; + *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";; + esac || + as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;; + esac + case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac + as_fn_append ac_file_inputs " '$ac_f'" + done + + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + configure_input='Generated from '` + $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g' + `' by configure.' + if test x"$ac_file" != x-; then + configure_input="$ac_file. $configure_input" + { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5 +$as_echo "$as_me: creating $ac_file" >&6;} + fi + # Neutralize special characters interpreted by sed in replacement strings. + case $configure_input in #( + *\&* | *\|* | *\\* ) + ac_sed_conf_input=`$as_echo "$configure_input" | + sed 's/[\\\\&|]/\\\\&/g'`;; #( + *) ac_sed_conf_input=$configure_input;; + esac + + case $ac_tag in + *:-:* | *:-) cat >"$ac_tmp/stdin" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;; + esac + ;; + esac + + ac_dir=`$as_dirname -- "$ac_file" || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| . 2>/dev/null || +$as_echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ + s//\1/ + q + } + /^X\(\/\/\)[^/].*/{ + s//\1/ + q + } + /^X\(\/\/\)$/{ + s//\1/ + q + } + /^X\(\/\).*/{ + s//\1/ + q + } + s/.*/./; q'` + as_dir="$ac_dir"; as_fn_mkdir_p + ac_builddir=. + +case "$ac_dir" in +.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;; +*) + ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'` + # A ".." for each directory in $ac_dir_suffix. + ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'` + case $ac_top_builddir_sub in + "") ac_top_builddir_sub=. ac_top_build_prefix= ;; + *) ac_top_build_prefix=$ac_top_builddir_sub/ ;; + esac ;; +esac +ac_abs_top_builddir=$ac_pwd +ac_abs_builddir=$ac_pwd$ac_dir_suffix +# for backward compatibility: +ac_top_builddir=$ac_top_build_prefix + +case $srcdir in + .) # We are building in place. + ac_srcdir=. + ac_top_srcdir=$ac_top_builddir_sub + ac_abs_top_srcdir=$ac_pwd ;; + [\\/]* | ?:[\\/]* ) # Absolute name. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir + ac_abs_top_srcdir=$srcdir ;; + *) # Relative name. + ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_build_prefix$srcdir + ac_abs_top_srcdir=$ac_pwd/$srcdir ;; +esac +ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix + + + case $ac_mode in + :F) + # + # CONFIG_FILE + # + +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +# If the template does not know about datarootdir, expand it. +# FIXME: This hack should be removed a few years after 2.60. +ac_datarootdir_hack=; ac_datarootdir_seen= +ac_sed_dataroot=' +/datarootdir/ { + p + q +} +/@datadir@/p +/@docdir@/p +/@infodir@/p +/@localedir@/p +/@mandir@/p' +case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in +*datarootdir*) ac_datarootdir_seen=yes;; +*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*) + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5 +$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;} +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 + ac_datarootdir_hack=' + s&@datadir@&$datadir&g + s&@docdir@&$docdir&g + s&@infodir@&$infodir&g + s&@localedir@&$localedir&g + s&@mandir@&$mandir&g + s&\\\${datarootdir}&$datarootdir&g' ;; +esac +_ACEOF + +# Neutralize VPATH when `$srcdir' = `.'. +# Shell code in configure.ac might set extrasub. +# FIXME: do we really want to maintain this feature? +cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 +ac_sed_extra="$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s|@configure_input@|$ac_sed_conf_input|;t t +s&@top_builddir@&$ac_top_builddir_sub&;t t +s&@top_build_prefix@&$ac_top_build_prefix&;t t +s&@srcdir@&$ac_srcdir&;t t +s&@abs_srcdir@&$ac_abs_srcdir&;t t +s&@top_srcdir@&$ac_top_srcdir&;t t +s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t +s&@builddir@&$ac_builddir&;t t +s&@abs_builddir@&$ac_abs_builddir&;t t +s&@abs_top_builddir@&$ac_abs_top_builddir&;t t +$ac_datarootdir_hack +" +eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \ + >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + +test -z "$ac_datarootdir_hack$ac_datarootdir_seen" && + { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } && + { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \ + "$ac_tmp/out"`; test -z "$ac_out"; } && + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&5 +$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir' +which seems to be undefined. Please make sure it is defined" >&2;} + + rm -f "$ac_tmp/stdin" + case $ac_file in + -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";; + *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";; + esac \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + ;; + :H) + # + # CONFIG_HEADER + # + if test x"$ac_file" != x-; then + { + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" + } >"$ac_tmp/config.h" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then + { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5 +$as_echo "$as_me: $ac_file is unchanged" >&6;} + else + rm -f "$ac_file" + mv "$ac_tmp/config.h" "$ac_file" \ + || as_fn_error $? "could not create $ac_file" "$LINENO" 5 + fi + else + $as_echo "/* $configure_input */" \ + && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \ + || as_fn_error $? "could not create -" "$LINENO" 5 + fi + ;; + + + esac + +done # for ac_tag + + +as_fn_exit 0 +_ACEOF +ac_clean_files=$ac_clean_files_save + +test $ac_write_fail = 0 || + as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5 + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || as_fn_exit 1 +fi +if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5 +$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} +fi + diff --git a/src/configure.ac b/src/configure.ac new file mode 100644 index 0000000..630d56d --- /dev/null +++ b/src/configure.ac @@ -0,0 +1,256 @@ +AC_PREREQ([2.60]) +AC_INIT([Octave-Forge communications package], [0]) + +AC_CONFIG_HEADERS([config.h]) + +# Avoid warnings for redefining AH-generated preprocessor symbols of +# Octave. +AH_TOP([#include "undef-ah-octave.h"]) + +AC_CONFIG_MACRO_DIRS([m4]) + +AC_ARG_VAR([MKOCTFILE], [mkoctfile compiler helper command]) +AC_ARG_VAR([OCTAVE], [Octave interpreter command]) +AC_CHECK_PROG([MKOCTFILE], mkoctfile, mkoctfile, []) +AC_CHECK_PROG([OCTAVE], octave, octave, []) +AC_PROG_CXX +AC_PROG_SED + +# Checks for octave depreciated symbols +## Simple symbol alternatives of different Octave versions. +AC_LANG(C++) +save_altsyms_CXX="$CXX" +save_altsyms_CXXFLAGS="$CXXFLAGS" +save_altsyms_CPPFLAGS="$CPPFLAGS" +save_altsyms_LDFLAGS="$LDFLAGS" +save_altsyms_LIBS="$LIBS" +OCTINCLUDEDIR=${OCTINCLUDEDIR:-`$MKOCTFILE -p INCFLAGS`} +OCTLIBDIR=${OCTLIBDIR:-`$MKOCTFILE -p OCTLIBDIR`} +CXX=`${MKOCTFILE} -p CXX` +CPPFLAGS="$OCTINCLUDEDIR $CPPFLAGS" +LDFLAGS="-L$OCTLIBDIR $LDFLAGS" +LIBS="-loctinterp $LIBS" + +OF_OCTAVE_LIST_ALT_SYMS([ +[dnl + [gripe_nonconformant], + [octave::err_nonconformant], + [[octave::err_nonconformant ("a",0,0)]], + [OCTAVE__ERR_NONCONFORMANT], + [[#include ]], + [[#include ]] +], + +[dnl + [gripe_wrong_type_arg], + [err_wrong_type_arg], + [[err_wrong_type_arg ("a", "b")]], + [OCTAVE__ERR_WRONG_TYPE_ARG], + [[#include ]], + [[#include ]] +], + +[dnl + [gripe_square_matrix_required], + [err_square_matrix_required], + [[err_square_matrix_required ("a", "b")]], + [DELOCTAVE__ERR_SQUARE_MATRIX_REQUIRED], + [[#include ]], + [[#include ]] +], + +[dnl + [gripe_invalid_conversion], + [err_invalid_conversion], + [[err_invalid_conversion ("a", "b")]], + [OCTAVE__ERR_INVALID_CONVERSION], + [[#include ]], + [[#include ]] +], + +[dnl + [gripe_implicit_conversion], + [warn_implicit_conversion], + [[warn_implicit_conversion ("a", "b", "c")]], + [OCTAVE__WARN_INVALID_CONVERSION], + [[#include ]], + [[#include ]] +], + +[dnl + [flush_octave_stdout], + [octave::flush_stdout], + [[octave::flush_stdout ();]], + [OCTAVE__FLUSH_STDOUT], + [[]], + [[]] +], + +[dnl + [is_complex_type], + [iscomplex], + [[octave_value ().iscomplex ();]], + [OV_ISCOMPLEX], + [], + [] +], + +[dnl + [is_real_type], + [isreal], + [[octave_value ().isreal ();]], + [OV_ISREAL], + [], + [] +], + +[dnl + [is_numeric_type], + [isnumeric], + [[octave_value ().isnumeric ();]], + [OV_ISNUMERIC], + [], + [] +], + +[dnl + [is_empty], + [isempty], + [[octave_value ().isempty ();]], + [OV_ISEMPTY], + [], + [] +], + +[dnl + [oct_mach_info::float_format], + [octave::mach_info::float_format], + [[octave::mach_info::float_format fmt;]], + [OCTAVE_MACH_INFO_FLOAT_FORMAT], + [], + [] +] + +],[oct-alt-includes.h]) + +AC_CHECK_HEADERS([octave/oct.h]) +AC_CHECK_HEADERS([octave/base-lu.h]) +AC_CHECK_HEADERS([octave/lu.h]) +AC_CHECK_HEADERS([octave/gripes.h]) +AC_CHECK_HEADERS([octave/errwarn.h]) +AC_CHECK_HEADERS([octave/ovl.h]) +AC_CHECK_HEADERS([octave/oct-obj.h]) +AC_CHECK_HEADERS([octave/ls-oct-ascii.h]) +AC_CHECK_HEADERS([octave/ls-oct-text.h]) +AC_CHECK_HEADERS([octave/oct-obj.h]) +AC_CHECK_HEADERS([octave/interpreter.h]) + +CXX=$save_altsyms_CXX +CXXFLAGS=$save_altsyms_CXXFLAGS +CPPFLAGS=$save_altsyms_CPPFLAGS +LDFLAGS=$save_altsyms_LDFLAGS +LIBS=$save_altsyms_LIBS + +have_hdf5=no +# check for HDF5 using pkg-config +PKG_CHECK_MODULES([HDF5],[hdf5], + [have_hdf5=yes ], + [] +) +if test $have_hdf5 = no; then + save_CPPFLAGS="$CPPFLAGS" + save_LIBS="$LIBS" + AC_CHECK_LIB(hdf5,H5Fopen, + [ + have_hdf5=yes + AC_CHECK_HEADERS([hdf5.h]) + HDF5_LIBS=-lhdf5 + ], + [], + ) + CPPFLAGS="$save_CPPFLAGS" + LIBS="$save_LIBS" +fi +if test $have_hdf5 = no; then + AC_MSG_ERROR([hdf5 not found]) +fi + +comm_OCT_EVAL="$OCTAVE --norc --no-history --silent --eval" + +comm_CXXFLAGS=`$MKOCTFILE -p ALL_CXXFLAGS` + +AC_CACHE_CHECK([for octave_hdf5_id type], + [comm_cv_octave_hdf5_id_type], + [comm_save_CPPFLAGS=$CPPFLAGS + comm_save_CXXFLAGS=$CXXFLAGS + CPPFLAGS="$CPPFLAGS $HDF5_CFLAGS" + CXXFLAGS="$CXXFLAGS $comm_CXXFLAGS" + AC_LANG_PUSH(C++) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + #include + #include + ]], [[ + octave_hdf5_id x; + ]])], + [comm_cv_octave_hdf5_id_type=yes], + [comm_cv_octave_hdf5_id_type=no]) + AC_LANG_POP(C++) + CPPFLAGS=$comm_save_CPPFLAGS + CXXFLAGS=$comm_save_CXXFLAGS]) +if test $comm_cv_octave_hdf5_id_type = yes; then + AC_DEFINE([HAVE_OCTAVE_HDF5_ID_TYPE],[1],[Define if have octave_hdf5_id]) +fi + +AC_CACHE_CHECK([for octave_base_value::gripe_load and octave_base_value::gripe_save], + [comm_cv_octave_base_value_gripe_load_save], + [comm_save_CPPFLAGS=$CPPFLAGS + comm_save_CXXFLAGS=$CXXFLAGS + CPPFLAGS="$CPPFLAGS $HDF5_CFLAGS" + CXXFLAGS="$CXXFLAGS $comm_CXXFLAGS" + AC_LANG_PUSH(C++) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + #include + #include + class foo : public octave_base_value + { + public: + foo () {} + void func () { gripe_load ("func"); gripe_save ("func"); } + }; + ]], [[ + foo x; + ]])], + [comm_cv_octave_base_value_gripe_load_save=yes], + [comm_cv_octave_base_value_gripe_load_save=no]) + AC_LANG_POP(C++) + CPPFLAGS=$comm_save_CPPFLAGS + CXXFLAGS=$comm_save_CXXFLAGS]) +if test $comm_cv_octave_base_value_gripe_load_save = yes; then + AC_DEFINE([HAVE_OCTAVE_BASE_VALUE_GRIPE_LOAD_SAVE],[1],[Define if have gripe_load and gripe_save]) +fi + +AC_CACHE_CHECK([whether octave_base_value::print is const-qualified], + [comm_cv_octave_base_value_print_const_qualified], + [comm_save_CPPFLAGS=$CPPFLAGS + comm_save_CXXFLAGS=$CXXFLAGS + CPPFLAGS="$CPPFLAGS $HDF5_CFLAGS" + CXXFLAGS="$CXXFLAGS $comm_CXXFLAGS" + AC_LANG_PUSH(C++) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + #include + #include + #include + ]], [[ + const octave_base_value x; x.print (std::cout); + ]])], + [comm_cv_octave_base_value_print_const_qualified=yes], + [comm_cv_octave_base_value_print_const_qualified=no]) + AC_LANG_POP(C++) + CPPFLAGS=$comm_save_CPPFLAGS + CXXFLAGS=$comm_save_CXXFLAGS]) +if test $comm_cv_octave_base_value_print_const_qualified = yes; then + AC_DEFINE([HAVE_OCTAVE_BASE_VALUE_PRINT_CONST],[1],[Define if octave_base_value::print is const-qualified]) +fi + +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT diff --git a/src/cyclgen.cc b/src/cyclgen.cc new file mode 100644 index 0000000..66ba18c --- /dev/null +++ b/src/cyclgen.cc @@ -0,0 +1,282 @@ +//Copyright (C) 2003 David Bateman +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of the +// License, or (at your option) any later version. +// +// This program 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 +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, see +// . +// +// In addition to the terms of the GPL, you are permitted to link this +// program with any Open Source program, as defined by the Open Source +// Initiative (www.opensource.org) + +#include + +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +// A simplified version of the filter function for specific lengths of a and b +// in the Galois field GF(2) +Array +filter_gf2 (const Array& b, const Array& a, + const Array& x, const int& n) +{ + + int x_len = x.numel (); + Array si (dim_vector (n, 1), 0); + Array y (dim_vector (x_len, 1), 0); + + for (int i = 0; i < x_len; i++) + { + y(i) = si(0); + if (b(0) && x(i)) + y(i) ^= 1; + + for (int j = 0; j < n - 1; j++) + { + si(j) = si(j+1); + if (a(j+1) && y(i)) + si(j) ^= 1; + if (b(j+1) && x(i)) + si(j) ^= 1; + } + si(n-1) = 0; + if (a(n) && y(i)) + si(n-1) ^= 1; + if (b(n) && x(i)) + si(n-1) ^= 1; + } + + return y; +} + +// Cyclic polynomial is irreducible. I.E. it divides into x^n-1 +// without remainder There must surely be an easier way of doing this +// as the polynomials are over GF(2). +static bool +do_is_cyclic_polynomial (const Array& a, const int& n, const int& m) +{ + Array y (dim_vector (n+1, 1), 0); + Array x (dim_vector (n-m+2, 1), 0); + y(0) = 1; + y(n) = 1; + x(0) = 1; + + Array b = filter_gf2 (y, a, x, n); + b.resize (dim_vector (n+1, 1), 0); + Array p (dim_vector (m+1, 1), 0); + p(0) = 1; + Array q = filter_gf2 (a, p, b, m); + + for (int i = 0; i < n+1; i++) + if (y(i) ^ q(i)) + return false; + + return true; +} + +DEFUN_DLD (cyclgen, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{h} =} cyclgen (@var{n}, @var{p})\n\ +@deftypefnx {Loadable Function} {@var{h} =} cyclgen (@var{n}, @var{p}, @var{typ})\n\ +@deftypefnx {Loadable Function} {[@var{h}, @var{g}] =} cyclgen (@dots{})\n\ +@deftypefnx {Loadable Function} {[@var{h}, @var{g}, @var{k}] =} cyclgen (@dots{})\n\ +Produce the parity check and generator matrix of a cyclic code. The parity\n\ +check matrix is returned as a @var{m} by @var{n} matrix, representing the\n\ +[@var{n},@var{k}] cyclic code. @var{m} is the order of the generator\n\ +polynomial @var{p} and the message length @var{k} is given by\n\ +@code{@var{n} - @var{m}}.\n\ +\n\ +The generator polynomial can either be a vector of ones and zeros,\n\ +and length @var{m} representing,\n\ +@tex\n\ +$$ p_0 + p_1 x + p_2 x^2 + \\cdots + p_m x^{m-1} $$\n\ +@end tex\n\ +@ifnottex\n\ +\n\ +@example\n\ +@var{p}(1) + @var{p}(2) * x + @var{p}(3) * x^2 + ... + @var{p}(@var{m}) * x^(m-1)\n\ +@end example\n\ +@end ifnottex\n\ +\n\ +The terms of the polynomial are stored least-significant term first.\n\ +Alternatively, @var{p} can be an integer representation of the same\n\ +polynomial.\n\ +\n\ +The form of the parity check matrix is determined by @var{typ}. If\n\ +@var{typ} is 'system', a systematic parity check matrix is produced. If\n\ +@var{typ} is 'nosys' and non-systematic parity check matrix is produced.\n\ +\n\ +If requested @code{cyclgen} also returns the @var{k} by @var{n} generator\n\ +matrix @var{g}.\ +\n\ +@seealso{hammgen, gen2par, cyclpoly}\n\ +@end deftypefn") +{ + octave_value_list retval; + int nargin = args.length (); + unsigned long long p = 0; + int n, m, k, mm; + bool system = true; + Array pp; + + if (nargin < 2 || nargin > 3) + { + print_usage (); + return retval; + } + + n = args(0).int_value (); + m = 1; + while (n > (1<<(m+1))) + m++; + pp.resize (dim_vector (n+1, 1), 0); + + if (args(1).is_scalar_type ()) + { + p = (unsigned long long)(args(1).int_value ()); + mm = 1; + while (p > ((unsigned long long)1<<(mm+1))) + mm++; + for (int i = 0; i < mm+1; i++) + pp(i) = (p & (1< 2) + { + if (args(2).is_string ()) + { + std::string s_arg = args(2).string_value (); + + if (s_arg == "system") + system = true; + else if (s_arg == "nosys") + system = false; + else + { + error ("cyclgen: illegal argument"); + return retval; + } + } + else + { + error ("cyclgen: illegal argument"); + return retval; + } + } + + // Haven't implemented this since I'm not sure what matlab wants here + if (!system) + { + error ("cyclgen: non-systematic generator matrices not implemented"); + return retval; + } + + if (!do_is_cyclic_polynomial (pp, n, mm)) + { + error ("cyclgen: generator polynomial does not produce cyclic code"); + return retval; + } + + unsigned long long mask = 1; + unsigned long long *alpha_to = + (unsigned long long *)malloc (sizeof (unsigned long long) * n); + for (int i = 0; i < n; i++) + { + alpha_to[i] = mask; + mask <<= 1; + if (mask & ((unsigned long long)1< 1) + { + Matrix generator (k, n, 0); + + for (int i = 0; i < (int)k; i++) + for (int j = 0; j < (int)mm; j++) + generator(i, j) = parity(j, i+mm); + for (int i = 0; i < (int)k; i++) + generator(i, i+mm) = 1; + + retval(1) = octave_value (generator); + retval(2) = octave_value ((double)k); + } + return retval; +} + +/* +%% Test input validation +%!error cyclgen () +%!error cyclgen (1) +%!error cyclgen (1, 2, 3, 4) +*/ + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/cyclpoly.cc b/src/cyclpoly.cc new file mode 100644 index 0000000..75a74bd --- /dev/null +++ b/src/cyclpoly.cc @@ -0,0 +1,286 @@ +//Copyright (C) 2003 David Bateman +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of the +// License, or (at your option) any later version. +// +// This program 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 +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, see +// . +// +// In addition to the terms of the GPL, you are permitted to link this +// program with any Open Source program, as defined by the Open Source +// Initiative (www.opensource.org) + +#include +#include + +#include + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +enum cyclic_poly_type +{ + CYCLIC_POLY_MIN=0, + CYCLIC_POLY_MAX, + CYCLIC_POLY_ALL, + CYCLIC_POLY_L +}; + +// A simplified version of the filter function for specific lengths of +// a and b in the Galois field GF(2) +Array +filter_gf2 (const Array& b, const Array& a, + const Array& x, const int& n) +{ + + int x_len = x.numel (); + Array si (dim_vector (n, 1), 0); + Array y (dim_vector (x_len, 1), 0); + + for (int i = 0; i < x_len; i++) + { + y(i) = si(0); + if (b(0) && x(i)) + y(i) ^= 1; + + for (int j = 0; j < n - 1; j++) + { + si(j) = si(j+1); + if (a(j+1) && y(i)) + si(j) ^= 1; + if (b(j+1) && x(i)) + si(j) ^= 1; + } + si(n-1) = 0; + if (a(n) && y(i)) + si(n-1) ^= 1; + if (b(n) && x(i)) + si(n-1) ^= 1; + } + + return y; +} + +// Cyclic polynomial is irreducible. I.E. it divides into x^n-1 +// without remainder There must surely be an easier way of doing this +// as the polynomials are over GF(2). +static bool +do_is_cyclic_polynomial (const unsigned long long& a1, const int& n, + const int& m) +{ + Array a (dim_vector (n+1, 1), 0); + Array y (dim_vector (n+1, 1), 0); + Array x (dim_vector (n-m+2, 1), 0); + y(0) = 1; + y(n) = 1; + x(0) = 1; + for (int i=0; i < m+1; i++) + a(i) = (a1 & (1UL << i) ? 1 : 0); + + Array b = filter_gf2 (y, a, x, n); + b.resize(dim_vector (n+1, 1), 0); + Array p (dim_vector (m+1, 1), 0); + p(0) = 1; + Array q = filter_gf2 (a, p, b, m); + + for (int i=0; i < n+1; i++) + if (y(i) ^ q(i)) + return false; + + return true; +} + +DEFUN_DLD (cyclpoly, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{y} =} cyclpoly (@var{n}, @var{k})\n\ +@deftypefnx {Loadable Function} {@var{y} =} cyclpoly (@var{n}, @var{k}, @var{opt})\n\ +@deftypefnx {Loadable Function} {@var{y} =} cyclpoly (@var{n}, @var{k}, @var{opt}, @var{rep})\n\ +This function returns the cyclic generator polynomials of the code\n\ +[@var{n},@var{k}]. By default the polynomial with the smallest weight\n\ +is returned. However this behavior can be overridden with the @var{opt}\n\ +flag. Valid values of @var{opt} are:\n\ +\n\ +@table @asis\n\ +@item @code{\"all\"}\n\ +Returns all of the polynomials of the code [@var{n},@var{k}]\n\ +@item @code{\"min\"}\n\ +Returns the polynomial of minimum weight of the code [@var{n},@var{k}]\n\ +@item @code{\"max\"}\n\ +Returns the polynomial of the maximum weight of the code [@var{n},@var{k}]\n\ +@item @var{l}\n\ +Returns the polynomials having exactly the weight @var{l}\n\ +@end table\n\ +\n\ +The polynomials are returns as row-vectors in the variable @var{y}. Each\n\ +row of @var{y} represents a polynomial with the least-significant term\n\ +first. The polynomials can be returned with an integer representation\n\ +if @var{rep} is @code{\"integer\"}. The default behavior is given if @var{rep}\n\ +is @code{\"polynomial\"}.\n\ +@seealso{gf, isprimitive}\n\ +@end deftypefn") +{ + octave_value retval; + int nargin = args.length (); + bool polyrep = true; + enum cyclic_poly_type type = CYCLIC_POLY_MIN; + RowVector cyclic_polys; + int l=0; + + if (nargin < 2 || nargin > 4) + { + print_usage (); + return retval; + } + + int n = args(0).int_value (); + int k = args(1).int_value ();; + + if (n < 1) + { + error ("cyclpoly: n must be 1 or greater"); + return retval; + } + + if (n <= k) + { + error ("cyclpoly: k must be less than n"); + return retval; + } + + for (int i = 2; i < nargin; i++) + { + if (args(i).is_scalar_type ()) + { + l = args(i).int_value (); + type = CYCLIC_POLY_L; + } + else if (args(i).is_string ()) + { + std::string s_arg = args(i).string_value (); + + if (s_arg == "integer") + polyrep = false; + else if (s_arg == "polynomial") + polyrep = true; + else if (s_arg == "min") + type = CYCLIC_POLY_MIN; + else if (s_arg == "max") + type = CYCLIC_POLY_MAX; + else if (s_arg == "all") + type = CYCLIC_POLY_ALL; + else + { + error ("cyclpoly: invalid argument"); + return retval; + } + } + else + { + error ("cyclpoly: incorrect argument type"); + return retval; + } + } + + int m = n - k; + + // Matlab code seems to think that 1+x+x^3 is of larger weight than + // 1+x^2+x^3. So for matlab compatiability the list of polynomials + // should be reversed by replacing "i+=2" with "i-=2" and visa-versa. + // Thats not going to happen!!! + + switch (type) + { + case CYCLIC_POLY_MIN: + cyclic_polys.resize (1); + for (unsigned long long i = (1UL< (1UL<. +// +// In addition to the terms of the GPL, you are permitted to link this +// program with any Open Source program, as defined by the Open Source +// Initiative (www.opensource.org) + +#include "galois.h" + +void +gripe_nonconformant_galois (const char *op, int op1_m, int op1_primpoly, + int op2_m, int op2_primpoly) +{ + (*current_liboctave_error_handler) + ("%s: nonconformant arguments. op1 is GF(2^%d) " + "(primitive polynomial %d), op2 is GF(2^%d) (primitive polynomial %d)", + op, op1_m, op1_primpoly, op2_m, op2_primpoly); +} + +void +gripe_nonconformant_galois (const char *op, int m) +{ + (*current_liboctave_error_handler) + ("%s: element exceeds range of galois field GF(2^%d)", op, m); +} + +void +gripe_divzero_galois (const char *op) +{ + (*current_liboctave_error_handler) + ("%s: division by zero in galois field", op); +} + +void +gripe_invalid_galois (void) +{ + (*current_liboctave_error_handler) + ("invalid data in Galois Field"); +} + +void +gripe_range_galois (int m) +{ + (*current_liboctave_error_handler) + ("data outside range of Galois Field GF(2^%d)", m); +} + +void +gripe_integer_galois (void) +{ + (*current_liboctave_error_handler) + ("data in Galois Field must be integer"); +} + +void +gripe_copy_invalid_galois (void) +{ + (*current_liboctave_error_handler) + ("trying to copy invalid Galois Field"); +} + +void +gripe_differ_galois (void) +{ + (*current_liboctave_error_handler) + ("can not assign data between two different Galois Fields"); +} + +void +gripe_invalid_table_galois (void) +{ + (*current_liboctave_error_handler) + ("invalid lookup table in Galois Field"); +} + +void +gripe_square_galois (void) +{ + (*current_liboctave_error_handler) + ("for A^x, A must be square and x scalar"); +} + +void +gripe_integer_power_galois (void) +{ + (*current_liboctave_error_handler) + ("exponent must be integer for binary operator '^' with galois field"); +} + +void +gripe_order_galois (int m) +{ + (*current_liboctave_error_handler) + ("invalid order %d for Galois Field", m); +} + +void +gripe_degree_galois (int m) +{ + (*current_liboctave_error_handler) + ("invalid degree for primitive polynomial (%d) of Galois Field", m); +} + +void +gripe_irred_galois (int m) +{ + (*current_liboctave_error_handler) + ("primitive polynomial (%d) of Galois Field must be irreducible", m); +} + +void +gripe_init_galois (void) +{ + (*current_liboctave_error_handler) + ("unable to initialize Galois Field"); +} + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/galois-def.h b/src/galois-def.h new file mode 100644 index 0000000..42b77c9 --- /dev/null +++ b/src/galois-def.h @@ -0,0 +1,415 @@ +//Copyright (C) 2003 David Bateman +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of the +// License, or (at your option) any later version. +// +// This program 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 +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, see +// . +// +// In addition to the terms of the GPL, you are permitted to link this +// program with any Open Source program, as defined by the Open Source +// Initiative (www.opensource.org) + +#if !defined (octave_galois_defs_h) +#define octave_galois_defs_h 1 + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +void gripe_nonconformant_galois (const char *op, int op1_m, int op1_primpoly, + int op2_m, int op2_primpoly); +void gripe_nonconformant_galois (const char *op, int m); +void gripe_divzero_galois (const char *op); +void gripe_invalid_galois (void); +void gripe_range_galois (int m); +void gripe_integer_galois (void); +void gripe_copy_invalid_galois (void); +void gripe_differ_galois (void); +void gripe_invalid_table_galois (void); +void gripe_square_galois (void); +void gripe_integer_power_galois (void); +void gripe_order_galois (int m); +void gripe_degree_galois (int m); +void gripe_irred_galois (int m); +void gripe_init_galois (void); + +// Compute X % N, where N is 2^M - 1, without a slow divide +#define MODN(X, M, N) \ + { \ + while (X >= N) \ + { \ + X -= N; \ + X = (X >> M) + (X & N); \ + } \ + } + +#define CHECK_GALOIS(OP, RET, M1, M2, NN) \ + { \ + if (!M1.have_field () || !M2.have_field ()) \ + { \ + gripe_invalid_galois (); \ + return RET (); \ + } \ + if ((M1.primpoly () != M2.primpoly ()) || (M1.m () != M2.m ())) \ + { \ + gripe_nonconformant_galois (OP, M1.m (), M1.primpoly (), M2.m (), M2.primpoly ()); \ + return RET (); \ + } \ + } + +#define CHECK_MATRIX(OP, RET, M1, M2, NN) \ + { \ + int nr = M1.rows (); \ + int nc = M1.cols (); \ + \ + if (!M1.have_field ()) \ + { \ + gripe_invalid_galois (); \ + return RET (); \ + } \ + for (int i = 0; i < nr; i++) \ + for (int j = 0; j < nc; j++) \ + { \ + if ((M1(i, j) < 0) || (M1(i, j) > NN)) \ + { \ + gripe_nonconformant_galois (OP, M1.m ()); \ + return RET (); \ + } \ + if (((double)M1(i, j) - (double)((int)M1(i, j))) != 0.) \ + { \ + gripe_nonconformant_galois (OP, M1.m ()); \ + return RET (); \ + } \ + } \ + } + +#define CHECK_DIV_ZERO(OP, RET, M) \ + { \ + int nr = M.rows (); \ + int nc = M.cols (); \ + \ + for (int i = 0; i < nr; i++) \ + for (int j = 0; j < nc; j++) \ + { \ + if (M(i, j) == 0) \ + { \ + gripe_divzero_galois (OP); \ + return RET (); \ + } \ + } \ + } + +#define CHECK_NODIV_ZERO(OP, RET, M) + +#define MM_BIN_OP1(R, OP, M1, M2, GR1, GR2, CHECKTYPE) \ + R \ + OP (const M1& m1, const M2& m2) \ + { \ + R r (m ## GR1); \ + \ + int m1_nr = m1.rows (); \ + int m1_nc = m1.cols (); \ + \ + int m2_nr = m2.rows (); \ + int m2_nc = m2.cols (); \ + \ + CHECK_ ## CHECKTYPE (#OP, R, m ## GR1, m ## GR2, r.n ()); \ + \ + if (m1_nr != m2_nr || m1_nc != m2_nc) \ + { \ + if ((m1_nr == 1 && m1_nc == 1) && (m2_nr > 0 && m2_nc > 0)) \ + { \ + r.resize (dim_vector (m2_nr, m2_nc)); \ + for (int i = 0; i < m2_nr; i++) \ + for (int j = 0; j < m2_nc; j++) \ + r(i, j) = (int)m1(0, 0) ^ (int)m2(i, j); \ + } \ + else if ((m2_nr == 1 && m2_nc == 1) && (m1_nr > 0 && m1_nc > 0)) \ + { \ + r.resize (dim_vector (m1_nr, m1_nc)); \ + for (int i = 0; i < m1_nr; i++) \ + for (int j = 0; j < m1_nc; j++) \ + r(i, j) = (int)m1(i, j) ^ (int)m2(0, 0); \ + } \ + else \ + OCTAVE__ERR_NONCONFORMANT (#OP, m1_nr, m1_nc, m2_nr, m2_nc); \ + } \ + else \ + { \ + if (m1_nr > 0 && m1_nc > 0) \ + for (int i = 0; i < m1_nr; i++) \ + for (int j = 0; j < m1_nc; j++) \ + r(i, j) ^= (int) m ## GR2 (i, j); \ + } \ + \ + return r; \ + } + +#define MM_BIN_OP2(R, F, OP, M1, M2, NN, GR1, GR2, CHECKTYPE, ZEROCHECK) \ + R \ + F (const M1& m1, const M2& m2) \ + { \ + R r (m ## GR1); \ + \ + int m1_nr = m1.rows (); \ + int m1_nc = m1.cols (); \ + \ + int m2_nr = m2.rows (); \ + int m2_nc = m2.cols (); \ + \ + CHECK_ ## CHECKTYPE (#F, R, m ## GR1, m ## GR2, r.n ()); \ + \ + CHECK_ ## ZEROCHECK ## DIV_ZERO (#F, R, m2); \ + \ + if (m1_nr != m2_nr || m1_nc != m2_nc) \ + { \ + if ((m1_nr == 1 && m1_nc == 1) && (m2_nr > 0 && m2_nc > 0)) \ + { \ + r.resize (dim_vector (m2_nr, m2_nc)); \ + if (m1(0, 0) == 0) \ + { \ + for (int i = 0; i < m2_nr; i++) \ + for (int j = 0; j < m2_nc; j++) \ + r(i, j) = 0; \ + } \ + else \ + { \ + int indxm1 = r.index_of ((int)m1(0, 0)); \ + for (int i = 0; i < m2_nr; i++) \ + for (int j = 0; j < m2_nc; j++) \ + { \ + if (m2(i, j) == 0) \ + r(i, j) = 0; \ + else \ + { \ + r(i, j) = indxm1 OP r.index_of ((int)m2(i, j)) + NN; \ + MODN (r(i, j), r.m (), r.n ()); \ + r(i, j) = r.alpha_to (r(i, j)); \ + } \ + } \ + } \ + } \ + else if ((m2_nr == 1 && m2_nc == 1) && (m1_nr > 0 && m1_nc > 0)) \ + { \ + r.resize (dim_vector (m1_nr, m1_nc)); \ + if (m2(0, 0) == 0) \ + { \ + for (int i = 0; i < m1_nr; i++) \ + for (int j = 0; j < m1_nc; j++) \ + r(i, j) = 0; \ + } \ + else \ + { \ + int indxm2 = r.index_of ((int)m2(0, 0)); \ + for (int i = 0; i < m1_nr; i++) \ + for (int j = 0; j < m1_nc; j++) \ + { \ + if (m1(i, j) == 0) \ + r(i, j) = 0; \ + else \ + { \ + r(i, j) = r.index_of ((int)m1(i, j)) OP indxm2 + NN; \ + MODN (r(i, j), r.m (), r.n ()); \ + r(i, j) = r.alpha_to (r(i, j)); \ + } \ + } \ + } \ + } \ + else \ + OCTAVE__ERR_NONCONFORMANT (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ + } \ + else \ + if (m1_nr > 0 && m1_nc > 0) \ + for (int i = 0; i < m1_nr; i++) \ + for (int j = 0; j < m1_nc; j++) \ + { \ + if ((m1(i, j) == 0) || (m2(i, j) == 0)) \ + r(i, j) = 0; \ + else \ + { \ + r(i, j) = r.index_of ((int)m1(i, j)) OP r.index_of ((int)m2(i, j)) + NN; \ + MODN (r(i, j), r.m (), r.n ()); \ + r(i, j) = r.alpha_to (r(i, j)); \ + } \ + } \ + \ + return r; \ + } + +#define MM_BIN_OPS1(R, M1, M2, GR1, GR2, CHECK) \ + MM_BIN_OP1 (R, operator +, M1, M2, GR1, GR2, CHECK) \ + MM_BIN_OP1 (R, operator -, M1, M2, GR1, GR2, CHECK) \ + MM_BIN_OP2 (R, product, +, M1, M2, 0, GR1, GR2, CHECK, NO) \ + MM_BIN_OP2 (R, quotient, -, M1, M2, r.n (), GR1, GR2, CHECK, ) + +#define MM_BIN_OPS2(R, M1, M2, GR1, GR2, CHECK) \ + MM_BIN_OP1 (R, operator +, M1, M2, GR1, GR2, CHECK) + +#define MM_CMP_OP1(F, OP, M1, C1, M2, C2, GR1, GR2, CHECKTYPE) \ + boolMatrix \ + F (const M1& m1, const M2& m2) \ + { \ + boolMatrix r; \ + \ + int m1_nr = m1.rows (); \ + int m1_nc = m1.cols (); \ + \ + int m2_nr = m2.rows (); \ + int m2_nc = m2.cols (); \ + \ + CHECK_ ## CHECKTYPE (#F, boolMatrix, m ## GR1, m ## GR2, m ## GR1.n ()); \ + \ + if (m1_nr == m2_nr && m1_nc == m2_nc) \ + { \ + r.resize (m1_nr, m1_nc); \ + \ + for (int j = 0; j < m1_nc; j++) \ + for (int i = 0; i < m1_nr; i++) \ + r(i, j) = C1 (m1(i, j)) OP C2 (m2(i, j)); \ + } \ + else \ + { \ + if ((m1_nr == 1 && m1_nc == 1) && (m2_nr > 0 && m2_nc > 0)) \ + { \ + r.resize (m2_nr, m2_nc); \ + for (int i = 0; i < m2_nr; i++) \ + for (int j = 0; j < m2_nc; j++) \ + r(i, j) = C1 (m1(0, 0)) OP C2 (m2(i, j)); \ + } \ + else if ((m2_nr == 1 && m2_nc == 1) && (m1_nr > 0 && m1_nc > 0)) \ + { \ + r.resize (m1_nr, m1_nc); \ + for (int i = 0; i < m1_nr; i++) \ + for (int j = 0; j < m1_nc; j++) \ + r(i, j) = C1 (m1(i, j)) OP C2 (m2(0, 0)); \ + } \ + else \ + OCTAVE__ERR_NONCONFORMANT (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ + } \ + \ + return r; \ + } + +#define MM_CMP_OPS1(M1, C1, M2, C2, GR1, GR2, CHECK) \ + MM_CMP_OP1 (mx_el_lt, <, M1, C1, M2, C2, GR1, GR2, CHECK) \ + MM_CMP_OP1 (mx_el_le, <=, M1, C1, M2, C2, GR1, GR2, CHECK) \ + MM_CMP_OP1 (mx_el_ge, >=, M1, C1, M2, C2, GR1, GR2, CHECK) \ + MM_CMP_OP1 (mx_el_gt, >, M1, C1, M2, C2, GR1, GR2, CHECK) \ + MM_CMP_OP1 (mx_el_eq, ==, M1, , M2, , GR1, GR2, CHECK) \ + MM_CMP_OP1 (mx_el_ne, !=, M1, , M2, , GR1, GR2, CHECK) + +#define MM_BOOL_OP1(F, OP, M1, M2, ZERO, GR1, GR2, CHECKTYPE) \ + boolMatrix \ + F (const M1& m1, const M2& m2) \ + { \ + boolMatrix r; \ + \ + int m1_nr = m1.rows (); \ + int m1_nc = m1.cols (); \ + \ + int m2_nr = m2.rows (); \ + int m2_nc = m2.cols (); \ + \ + CHECK_ ## CHECKTYPE (#F, boolMatrix, m ## GR1, m ## GR2, m ## GR1.n ()); \ + \ + if (m1_nr == m2_nr && m1_nc == m2_nc) \ + { \ + if (m1_nr != 0 || m1_nc != 0) \ + { \ + r.resize (m1_nr, m1_nc); \ + \ + for (int j = 0; j < m1_nc; j++) \ + for (int i = 0; i < m1_nr; i++) \ + { \ + r(i, j) = (m1(i, j) != ZERO) \ + OP (m2(i, j) != ZERO); \ + } \ + } \ + } \ + else \ + { \ + if ((m1_nr == 1 && m1_nc == 1) && (m2_nr > 0 && m2_nc > 0)) \ + { \ + r.resize (m2_nr, m2_nc); \ + for (int i = 0; i < m2_nr; i++) \ + for (int j = 0; j < m2_nc; j++) \ + r(i, j) = (m1(0, 0) != ZERO) \ + OP (m2(i, j) != ZERO); \ + } \ + else if ((m2_nr == 1 && m2_nc == 1) && (m1_nr > 0 && m1_nc > 0)) \ + { \ + r.resize (m1_nr, m1_nc); \ + for (int i = 0; i < m1_nr; i++) \ + for (int j = 0; j < m1_nc; j++) \ + r(i, j) = (m1(i, j) != ZERO) \ + OP (m2(0, 0) != ZERO); \ + } \ + else if ((m1_nr != 0 || m1_nc != 0) && (m2_nr != 0 || m2_nc != 0)) \ + OCTAVE__ERR_NONCONFORMANT (#F, m1_nr, m1_nc, m2_nr, m2_nc); \ + } \ + \ + return r; \ + } + +#define MM_BOOL_OPS1(M1, M2, ZERO, GR1, GR2, CHECK) \ + MM_BOOL_OP1 (mx_el_and, &&, M1, M2, ZERO, GR1, GR2, CHECK) \ + MM_BOOL_OP1 (mx_el_or, ||, M1, M2, ZERO, GR1, GR2, CHECK) + +#define GALOIS_REDUCTION_OP(RET, ROW_EXPR, COL_EXPR, INIT_VAL, \ + MT_RESULT) \ + \ + int nr = rows (); \ + int nc = cols (); \ + \ + if (nr > 0 && nc > 0) \ + { \ + if ((nr == 1 && dim == -1) || dim == 1) \ + { \ + RET.resize (dim_vector (nr, 1)); \ + for (int i = 0; i < nr; i++) \ + { \ + RET (i, 0) = INIT_VAL; \ + for (int j = 0; j < nc; j++) \ + { \ + ROW_EXPR; \ + } \ + } \ + } \ + else \ + { \ + RET.resize (dim_vector (1, nc)); \ + for (int j = 0; j < nc; j++) \ + { \ + RET (0, j) = INIT_VAL; \ + for (int i = 0; i < nr; i++) \ + { \ + COL_EXPR; \ + } \ + } \ + } \ + } \ + else if (nc == 0 && (nr == 0 || (nr == 1 && dim == -1))) \ + RET.resize (dim_vector (1, 1), MT_RESULT); \ + else if (nr == 0 && (dim == 0 || dim == -1)) \ + RET.resize (dim_vector (1, nc), MT_RESULT); \ + else if (nc == 0 && dim == 1) \ + RET.resize (dim_vector (nr, 1), MT_RESULT); \ + else \ + RET.resize (dim_vector (nr > 0, nc > 0)); + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/galois-ops.h b/src/galois-ops.h new file mode 100644 index 0000000..dc74837 --- /dev/null +++ b/src/galois-ops.h @@ -0,0 +1,151 @@ +//Copyright (C) 2003 David Bateman +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of the +// License, or (at your option) any later version. +// +// This program 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 +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, see +// . +// +// In addition to the terms of the GPL, you are permitted to link this +// program with any Open Source program, as defined by the Open Source +// Initiative (www.opensource.org) + +#if !defined (galois_octave_ops_h) +#define galois_octave_ops_h 1 + +#if ! defined (CAST_BINOP_ARGS) +# define CAST_BINOP_ARGS(t1, t2) \ + t1 v1 = dynamic_cast (a1); \ + t2 v2 = dynamic_cast (a2) +#endif + +#if ! defined (CAST_UNOP_ARG) +# define CAST_UNOP_ARG(t) \ + t v = dynamic_cast (a) +#endif + +#if ! defined (BINOPDECL) +# define BINOPDECL(name, a1, a2) \ + static octave_value \ + CONCAT2(oct_binop_, name) (const octave_base_value& a1, \ + const octave_base_value& a2) +#endif + +#if ! defined (CATOPDECL) +# define CATOPDECL(name, a1, a2) \ + static octave_value \ + CONCAT2(oct_catop_, name) (octave_base_value& a1, \ + const octave_base_value& a2, \ + const Array& ra_idx) +#endif + +// Override the operator and function definition defines from Octave + +#define DEFBINOP_OP_G(name, t1, t2, op) \ + BINOPDECL (name, a1, a2) \ + { \ + CAST_BINOP_ARGS (const octave_ ## t1&, const octave_ ## t2&); \ + return new octave_galois \ + (v1.t1 ## _value () op v2.t2 ## _value ()); \ + } + +#define DEFBINOP_FN_G(name, t1, t2, f) \ + BINOPDECL (name, a1, a2) \ + { \ + CAST_BINOP_ARGS (const octave_ ## t1&, const octave_ ## t2&); \ + return new octave_galois (f (v1.t1 ## _value (), v2.t2 ## _value ())); \ + } + +#define DEFBINOP_OP_B_S1(name, t1, t2, op) \ + BINOPDECL (name, a1, a2) \ + { \ + CAST_BINOP_ARGS (const octave_ ## t1&, const octave_ ## t2&); \ + return octave_value \ + (v1.matrix_value () op v2.t2 ##_value ()); \ + } + +#define DEFBINOP_FN_B_S1(name, t1, t2, f) \ + BINOPDECL (name, a1, a2) \ + { \ + CAST_BINOP_ARGS (const octave_ ## t1&, const octave_ ## t2&); \ + return octave_value (f (v1.matrix_value (), v2.t2 ## _value ())); \ + } + +#define DEFBINOP_OP_G_S1(name, t1, t2, op) \ + BINOPDECL (name, a1, a2) \ + { \ + CAST_BINOP_ARGS (const octave_ ## t1&, const octave_ ## t2&); \ + return new octave_galois \ + (v1.matrix_value () op v2.t2 ## _value ()); \ + } + +#define DEFBINOP_FN_G_S1(name, t1, t2, f) \ + BINOPDECL (name, a1, a2) \ + { \ + CAST_BINOP_ARGS (const octave_ ## t1&, const octave_ ## t2&); \ + return new octave_galois (f (v1.matrix_value (), v2.t2 ## _value ())); \ + } + +#define DEFBINOP_OP_B_S2(name, t1, t2, op) \ + BINOPDECL (name, a1, a2) \ + { \ + CAST_BINOP_ARGS (const octave_ ## t1&, const octave_ ## t2&); \ + return octave_value \ + (v1.t1 ## _value () op v2.matrix_value ()); \ + } + +#define DEFBINOP_FN_B_S2(name, t1, t2, f) \ + BINOPDECL (name, a1, a2) \ + { \ + CAST_BINOP_ARGS (const octave_ ## t1&, const octave_ ## t2&); \ + return octave_value (f (v1.t1 ## _value (), v2.matrix_value ())); \ + } + +#define DEFBINOP_OP_G_S2(name, t1, t2, op) \ + BINOPDECL (name, a1, a2) \ + { \ + CAST_BINOP_ARGS (const octave_ ## t1&, const octave_ ## t2&); \ + return new octave_galois \ + (v1.t1 ## _value () op v2.matrix_value ()); \ + } + +#define DEFBINOP_FN_G_S2(name, t1, t2, f) \ + BINOPDECL (name, a1, a2) \ + { \ + CAST_BINOP_ARGS (const octave_ ## t1&, const octave_ ## t2&); \ + return new octave_galois (f (v1.t1 ## _value (), v2.matrix_value ())); \ + } + +#define DEFCATOP_G_FN(name, t1, t2, f) \ + CATOPDECL (name, a1, a2) \ + { \ + CAST_BINOP_ARGS (octave_ ## t1&, const octave_ ## t2&); \ + return new octave_galois (f (v1.t1 ## _value (), v2.t2 ## _value (), \ + ra_idx)); \ + } + +#define DEFCATOP_G_METHOD(name, t1, t2, f) \ + CATOPDECL (name, a1, a2) \ + { \ + CAST_BINOP_ARGS (octave_ ## t1&, const octave_ ## t2&); \ + return new octave_galois (v1.t1 ## _value (). f (v2.t2 ## _value (), \ + ra_idx)); \ + } + +#define INSTALL_G_CATOP(t1, t2, f) INSTALL_CATOP (t1, t2, f) + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/galois.cc b/src/galois.cc new file mode 100644 index 0000000..34d6e60 --- /dev/null +++ b/src/galois.cc @@ -0,0 +1,1507 @@ +//Copyright (C) 2003 David Bateman +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of the +// License, or (at your option) any later version. +// +// This program 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 +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, see +// . +// +// In addition to the terms of the GPL, you are permitted to link this +// program with any Open Source program, as defined by the Open Source +// Initiative (www.opensource.org) + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#ifdef HAVE_OCTAVE_GRIPES_H +#include +#endif +#ifdef HAVE_OCTAVE_ERRWARN_H +#include +#endif +#include + +#include "galois.h" +#include "galoisfield.h" +#include "galois-def.h" + +#ifdef HAVE_OCTAVE_BASE_LU_H +# include +#else +# include "base-lu.cc" +#endif + +galois_field_list stored_galois_fields; + +// galois class + +galois::galois (const Array& a, const int& _m, + const int& _primpoly) : MArray (a.dims ()), field (NULL) +{ + int _n = (1<<_m) - 1; + + // Check the validity of the data in the matrix + for (int i = 0; i < rows (); i++) + { + for (int j = 0; j < columns (); j++) + { + if ((a(i, j) < 0) || (a(i, j) > _n)) + { + gripe_range_galois (_m); + return; + } + xelem(i, j) = (int)a(i, j); + } + } + + field = stored_galois_fields.create_galois_field (_m, _primpoly); +} + +galois::galois (const MArray& a, const int& _m, + const int& _primpoly) : MArray (a.dims ()), field (NULL) +{ + int _n = (1<<_m) - 1; + + // Check the validity of the data in the matrix + for (int i = 0; i < rows (); i++) + { + for (int j = 0; j < columns (); j++) + { + if ((a(i, j) < 0) || (a(i, j) > _n)) + { + gripe_range_galois (_m); + return; + } + xelem(i, j) = (int)a(i, j); + } + } + + field = stored_galois_fields.create_galois_field (_m, _primpoly); +} + +galois::galois (const Matrix& a, const int& _m, + const int& _primpoly) : MArray (a.dims ()), field (NULL) +{ + int _n = (1<<_m) - 1; + + // Check the validity of the data in the matrix + for (int i = 0; i < rows (); i++) + { + for (int j = 0; j < columns (); j++) + { + if ((a(i, j) < 0) || (a(i, j) > _n)) + { + gripe_range_galois (_m); + return; + } + if ((a(i, j) - (double)((int)a(i, j))) != 0.) + { + gripe_integer_galois (); + return; + } + xelem(i, j) = (int)a(i, j); + } + } + + field = stored_galois_fields.create_galois_field (_m, _primpoly); +} + +galois::galois (int nr, int nc, const int& val, const int& _m, + const int& _primpoly) + : MArray (dim_vector (nr, nc), val), field (NULL) +{ + int _n = (1<<_m) - 1; + + // Check the validity of the data in the matrix + if ((val < 0) || (val > _n)) + { + gripe_range_galois (_m); + return; + } + + field = stored_galois_fields.create_galois_field (_m, _primpoly); +} + +galois::galois (int nr, int nc, double val, const int& _m, + const int& _primpoly) + : MArray (dim_vector (nr, nc), (int)val), field (NULL) +{ + int _n = (1<<_m) - 1; + + // Check the validity of the data in the matrix + if ((val < 0) || (val > _n)) + { + gripe_range_galois (_m); + return; + } + + if ((val - (double)((int)val)) != 0.) + { + gripe_integer_galois (); + return; + } + + field = stored_galois_fields.create_galois_field (_m, _primpoly); +} + +galois::galois (const galois& a) : MArray (a) +{ + + if (!a.have_field ()) + { + gripe_copy_invalid_galois (); + field = NULL; + return; + } + + // This call to create_galois_field will just increment the usage counter + field = stored_galois_fields.create_galois_field (a.m (), a.primpoly ()); +} + +galois::~galois (void) +{ + stored_galois_fields.delete_galois_field (field); + field = NULL; +} + +galois& +galois::operator = (const galois& t) +{ + if (!t.have_field ()) + { + gripe_copy_invalid_galois (); + if (have_field ()) + stored_galois_fields.delete_galois_field (field); + field = NULL; + return *this; + } + + if (have_field ()) + { + if ((m () != t.m ()) || (primpoly () != t.primpoly ())) + { + stored_galois_fields.delete_galois_field (field); + field = stored_galois_fields.create_galois_field (t.m (), t.primpoly ()); + } + } + else + field = stored_galois_fields.create_galois_field (t.m (), t.primpoly ()); + + // Copy the data + MArray::operator = (t); + + return *this; +} + +galois& +galois::operator += (const galois& a) +{ + int nr = rows (); + int nc = cols (); + + int a_nr = a.rows (); + int a_nc = a.cols (); + + if (have_field () && a.have_field ()) + { + if ((m () != a.m ()) || (primpoly () != a.primpoly ())) + { + gripe_differ_galois (); + return *this; + } + } + else + { + gripe_invalid_galois (); + return *this; + } + + if (nr != a_nr || nc != a_nc) + { + OCTAVE__ERR_NONCONFORMANT ("operator +=", nr, nc, a_nr, a_nc); + return *this; + } + + for (int i = 0; i < rows (); i++) + for (int j = 0; j < columns (); j++) + xelem(i, j) ^= a (i, j); + + return *this; +} + +galois& +galois::operator -= (const galois& a) +{ + int nr = rows (); + int nc = cols (); + + int a_nr = a.rows (); + int a_nc = a.cols (); + + if (have_field () && a.have_field ()) + { + if ((m () != a.m ()) || (primpoly () != a.primpoly ())) + { + gripe_differ_galois (); + return *this; + } + } + else + { + gripe_invalid_galois (); + return *this; + } + + if (nr != a_nr || nc != a_nc) + { + OCTAVE__ERR_NONCONFORMANT ("operator -=", nr, nc, a_nr, a_nc); + return *this; + } + + for (int i = 0; i < rows (); i++) + for (int j = 0; j < columns (); j++) + xelem(i, j) ^= a (i, j); + + return *this; +} + +galois +galois::index (idx_vector& i, int resize_ok, const int& rfv) const +{ + galois retval (MArray::index(i, resize_ok, rfv), m (), primpoly ()); + + return retval; +} + +galois +galois::index (idx_vector& i, idx_vector& j, int resize_ok, + const int& rfv) const +{ + galois retval (MArray::index(i, j, resize_ok, rfv), m (), primpoly ()); + + return retval; +} + +galois +galois::concat (const galois& rb, const Array& ra_idx) +{ + if (rb.numel () > 0) + insert (rb, ra_idx(0), ra_idx(1)); + return *this; +} + +galois +galois::concat (const Matrix& rb, const Array& ra_idx) +{ + if (numel () == 1) + return *this; + + galois tmp (0, 0, 0, m (), primpoly ()); + int _n = (1< _n)) + { + gripe_range_galois (m ()); + return *this; + } + if ((rb(i, j) - (double)((int)rb(i, j))) != 0.) + { + gripe_integer_galois (); + return *this; + } + tmp(i, j) = (int)rb(i, j); + } + } + + insert (tmp, ra_idx(0), ra_idx(1)); + return *this; +} + +galois +concat (const Matrix& ra, const galois& rb, const Array& ra_idx) +{ + galois retval (0, 0, 0, rb.m (), rb.primpoly ()); + int _n = (1< _n)) + { + gripe_range_galois (rb.m ()); + return retval; + } + if ((ra(i, j) - (double)((int)ra(i, j))) != 0.) + { + gripe_integer_galois (); + return retval; + } + retval(i, j) = (int)ra(i, j); +#else + int tmp = (int)ra(i, j); + if (tmp < 0) + retval(i, j) = 0; + else if (tmp > _n) + retval(i, j) = _n; + else + retval(i, j) = tmp; +#endif + } + } + + retval.insert (rb, ra_idx(0), ra_idx(1)); + return retval; +} + +galois& +galois::insert (const galois& t, int r, int c) +{ + if ((m () != t.m ()) || (primpoly () != t.primpoly ())) + (*current_liboctave_error_handler) ("inserted galois variable must " + "be in the same field"); + else + Array::insert (t, r, c); + return *this; +} + +galois +galois::diag (void) const +{ + return diag (0); +} + +galois +galois::diag (int k) const +{ + int nnr = rows (); + int nnc = cols (); + galois retval (0, 0, 0, m (), primpoly ()); + + if (k > 0) + nnc -= k; + else if (k < 0) + nnr += k; + + if (nnr > 0 && nnc > 0) + { + int ndiag = (nnr < nnc) ? nnr : nnc; + retval.resize (dim_vector (ndiag, 1)); + + if (k > 0) + { + for (int i = 0; i < ndiag; i++) + retval(i, 0) = xelem (i, i+k); + } + else if ( k < 0) + { + for (int i = 0; i < ndiag; i++) + retval(i, 0) = xelem (i-k, i); + } + else + { + for (int i = 0; i < ndiag; i++) + retval(i, 0) = xelem (i, i); + } + } + else + error ("diag: requested diagonal out of range"); + + return retval; +} + +// unary operations + +boolMatrix +galois::operator ! (void) const +{ + int nr = rows (); + int nc = cols (); + + boolMatrix b (nr, nc); + + for (int j = 0; j < nc; j++) + for (int i = 0; i < nr; i++) + b (i, j) = ! xelem (i, j); + + return b; +} + +galois +galois::transpose (void) const +{ + galois a (Matrix (0, 0), m (), primpoly ()); + int d1 = rows (); + int d2 = cols (); + + a.resize (dim_vector (d2, d1)); + for (int j = 0; j < d2; j++) + for (int i = 0; i < d1; i++) + a (j, i) = xelem (i, j); + + return a; +} + +static inline int +modn (int x, int m, int n) +{ + while (x >= n) + { + x -= n; + x = (x >> m) + (x & n); + } + return x; +} + +galois +elem_pow (const galois& a, const galois& b) +{ + int a_nr = a.rows (); + int a_nc = a.cols (); + galois result (a_nr, a_nc, 0, a.m (), a.primpoly ()); + + int b_nr = b.rows (); + int b_nc = b.cols (); + + if (a.have_field () && b.have_field ()) + { + if ((a.m () != b.m ()) || (a.primpoly () != b.primpoly ())) + { + gripe_differ_galois (); + return galois (); + } + } + else + { + gripe_invalid_galois (); + return galois (); + } + + if (a_nr == 1 && a_nc == 1) + { + result.resize (dim_vector (b_nr, b_nc), 0); + int tmp = a.index_of (a(0, 0)); + for (int j = 0; j < b_nc; j++) + for (int i = 0; i < b_nr; i++) + if (b(i, j) == 0) + result(i, j) = 1; + else if (a(0, 0) != 0) + result(i, j) = a.alpha_to (modn (tmp * b(i, j), a.m (), a.n ())); + } + else if (b_nr == 1 && b_nc == 1) + { + for (int j = 0; j < a_nc; j++) + for (int i = 0; i < a_nr; i++) + if (b(0, 0) == 0) + result(i, j) = 1; + else if (a(i, j) != 0) + result(i, j) = a.alpha_to (modn (a.index_of (a(i, j)) * + b(0, 0), a.m (), a.n ())); + } + else + { + if (a_nr != b_nr || a_nc != b_nc) + { + OCTAVE__ERR_NONCONFORMANT ("operator .^", a_nr, a_nc, a_nr, a_nc); + return galois (); + } + + for (int j = 0; j < a_nc; j++) + for (int i = 0; i < a_nr; i++) + if (b(i, j) == 0) + result(i, j) = 1; + else if (a(i, j) != 0) + result(i, j) = a.alpha_to (modn (a.index_of (a(i, j)) * + b(i, j), a.m (), a.n ())); + } + + return result; +} + +galois +elem_pow (const galois& a, const Matrix& b) +{ + int a_nr = a.rows (); + int a_nc = a.cols (); + galois result (a_nr, a_nc, 0, a.m (), a.primpoly ()); + + int b_nr = b.rows (); + int b_nc = b.cols (); + + if (b_nr == 1 && b_nc == 1) + return elem_pow (a, b(0, 0)); + + if (a_nr != b_nr || a_nc != b_nc) + { + OCTAVE__ERR_NONCONFORMANT ("operator .^", a_nr, a_nc, b_nr, b_nc); + return galois (); + } + + for (int j = 0; j < a_nc; j++) + for (int i = 0; i < a_nr; i++) + { + int tmp = (int)b(i, j); + while (tmp < 0) + tmp += a.n (); + if (tmp == 0) + result(i, j) = 1; + else if (a(i, j) != 0) + result(i, j) = a.alpha_to (modn (a.index_of (a(i, j)) * tmp, + a.m (), a.n ())); + } + return result; +} + +galois +elem_pow (const galois& a, double b) +{ + int a_nr = a.rows (); + int a_nc = a.cols (); + galois result (a_nr, a_nc, 0, a.m (), a.primpoly ()); + int bi = (int) b; + + if ((double)bi != b) + { + gripe_integer_galois (); + return galois (); + } + + while (bi < 0) + bi += a.n (); + + for (int j = 0; j < a_nc; j++) + for (int i = 0; i < a_nr; i++) + { + if (bi == 0) + result(i, j) = 1; + else if (a(i, j) != 0) + result(i, j) = a.alpha_to (modn (a.index_of (a(i, j)) * + bi, a.m (), a.n ())); + } + return result; +} + +galois +elem_pow (const galois &a, int b) +{ + int a_nr = a.rows (); + int a_nc = a.cols (); + galois result (a_nr, a_nc, 0, a.m (), a.primpoly ()); + + while (b < 0) + b += a.n (); + + for (int j = 0; j < a_nc; j++) + for (int i = 0; i < a_nr; i++) + { + if (b == 0) + result(i, j) = 1; + else if (a(i, j) != 0) + result(i, j) = a.alpha_to (modn (a.index_of (a(i, j)) * b, + a.m (), a.n ())); + } + return result; +} + +galois +pow (const galois& a, double b) +{ + int bi = (int)b; + if ((double)bi != b) + { + gripe_integer_power_galois (); + return galois (); + } + + return pow (a, bi); +} + +galois +pow (const galois& a, const galois& b) +{ + int nr = b.rows (); + int nc = b.cols (); + + if (a.have_field () && b.have_field ()) + { + if ((a.m () != b.m ()) || (a.primpoly () != b.primpoly ())) + { + gripe_differ_galois (); + return galois (); + } + } + else + { + gripe_invalid_galois (); + return galois (); + } + + if (nr != 1 || nc != 1) + { + gripe_square_galois (); + return galois (); + } + else + return pow (a, b(0, 0)); +} + +galois +pow (const galois& a, int b) +{ + galois retval; + int nr = a.rows (); + int nc = a.cols (); + + if (!a.have_field ()) + { + gripe_invalid_galois (); + return retval; + } + + if (nr == 0 || nc == 0 || nr != nc) + gripe_square_galois (); + else if (b == 0) + { + retval = galois (nr, nc, 0, a.m (), a.primpoly ()); + for (int i = 0; i < nr; i++) + retval(i, i) = 1; + } + else + { + galois atmp; + + if (b < 0 ) + { + atmp = a.inverse (); + b = abs (b); + } + else + atmp = a; + + retval = atmp; + b--; + while (b > 0) + { + if (b & 1) + retval = retval * atmp; + + b >>= 1; + + if (b > 0) + atmp = atmp * atmp; + } + } + + return retval; +} + +galois +operator * (const Matrix& a, const galois& b) +{ + galois tmp (a, b.m (), b.primpoly ()); + + OCTAVE_QUIT; + + return tmp * b; +} + +galois +operator * (const galois& a, const Matrix& b) +{ + galois tmp (b, a.m (), a.primpoly ()); + + OCTAVE_QUIT; + + return a * tmp; +} + +galois +operator * (const galois& a, const galois& b) +{ + if (a.have_field () && b.have_field ()) + { + if ((a.m () != b.m ()) || (a.primpoly () != b.primpoly ())) + { + gripe_differ_galois (); + return galois (); + } + } + else + { + gripe_invalid_galois (); + return galois (); + } + + int a_nr = a.rows (); + int a_nc = a.cols (); + + int b_nr = b.rows (); + int b_nc = b.cols (); + + if ((a_nr == 1 && a_nc == 1) || (b_nr == 1 && b_nc == 1)) + return product (a, b); + else if (a_nc != b_nr) + { + OCTAVE__ERR_NONCONFORMANT ("operator *", a_nr, a_nc, b_nr, b_nc); + return galois (); + } + else + { + galois retval (a_nr, b_nc, 0, a.m (), a.primpoly ()); + if (a_nr != 0 && a_nc != 0 && b_nc != 0) + { + // This is not optimum for referencing b, but can use vector + // to represent index(a(k,j)). Seems to be the fastest. + galois c (a_nr, 1, 0, a.m (), a.primpoly ()); + for (int j = 0; j < b_nr; j++) + { + for (int k = 0; k < a_nr; k++) + c(k, 0) = a.index_of (a(k, j)); + + for (int i = 0; i < b_nc; i++) + if (b(j, i) != 0) + { + int tmp = a.index_of (b(j, i)); + for (int k = 0; k < a_nr; k++) + { + if (a(k, j) != 0) + retval(k, i) = retval(k, i) + ^ a.alpha_to (modn (tmp + c(k, 0), + a.m (), a.n ())); + } + } + } + } + return retval; + } +} + +// Other operators +boolMatrix +galois::all (int dim) const +{ + return do_mx_red_op (*this, dim, mx_inline_all); +} + +boolMatrix +galois::any (int dim) const +{ + return do_mx_red_op (*this, dim, mx_inline_any); +} + +galois +galois::prod (int dim) const +{ + if (!have_field ()) + { + gripe_invalid_galois (); + return galois (); + } + + galois retval (0, 0, 0, m (), primpoly ()); + +#define ROW_EXPR \ + if ((retval(i, 0) == 0) || (elem (i, j) == 0)) \ + retval(i, 0) = 0; \ + else \ + retval(i, 0) = alpha_to (modn (index_of (retval(i, 0)) + \ + index_of (elem (i, j)), m (), n ())); + +#define COL_EXPR \ + if ((retval(0, j) == 0) || (elem (i, j) == 0)) \ + retval(0, j) = 0; \ + else \ + retval(0, j) = alpha_to (modn (index_of (retval(0, j)) + \ + index_of (elem (i, j)), m (), n ())); + + GALOIS_REDUCTION_OP (retval, ROW_EXPR, COL_EXPR, 1, 1); + return retval; + +#undef ROW_EXPR +#undef COL_EXPR +} + +galois +galois::sum (int dim) const +{ + if (!have_field ()) + { + gripe_invalid_galois (); + return galois (); + } + + galois retval (0, 0, 0, m (), primpoly ()); + + +#define ROW_EXPR \ + retval(i, 0) ^= elem (i, j); + +#define COL_EXPR \ + retval(0, j) ^= elem (i, j); + + GALOIS_REDUCTION_OP (retval, ROW_EXPR, COL_EXPR, 0, 0); + return retval; + +#undef ROW_EXPR +#undef COL_EXPR +} + +galois +galois::sumsq (int dim) const +{ + if (!have_field ()) + { + gripe_invalid_galois (); + return galois (); + } + + galois retval (0, 0, 0, m (), primpoly ()); + +#define ROW_EXPR \ + if (elem (i, j) != 0) \ + retval(i, 0) ^= alpha_to (modn (2*index_of (elem (i, j)), m (), n ())); + +#define COL_EXPR \ + if (elem (i, j) != 0) \ + retval(0, j) ^= alpha_to (modn (2*index_of (elem (i, j)), m (), n ())); + + GALOIS_REDUCTION_OP (retval, ROW_EXPR, COL_EXPR, 0, 0); + return retval; + +#undef ROW_EXPR +#undef COL_EXPR +} + +galois +galois::sqrt (void) const +{ + galois retval (*this); + int nr = rows (); + int nc = cols (); + + for (int j = 0; j < nc; j++) + { + for (int i = 0; i < nr; i++) + if (retval.index_of (retval(i, j)) & 1) + retval(i, j) = retval.alpha_to ((retval.index_of (retval(i, j)) + + retval.n ()) / 2); + else + retval(i, j) = retval.alpha_to (retval.index_of (retval(i, j)) + / 2); + } + return retval; +} + +galois +galois::log (void) const +{ + bool warned = false; + if (!have_field ()) + { + gripe_invalid_galois (); + return galois (); + } + + galois retval (*this); + int nr = rows (); + int nc = cols (); + + for (int j = 0; j < nc; j++) + for (int i = 0; i < nr; i++) + { + if (retval(i, j) == 0) + { + if (!warned) + { + warning ("log of zero undefined in Galois field"); + warned = true; + } + // How do I flag a NaN without either + // 1) Having to check everytime that the data is valid + // 2) Causing overflow in alpha_to or index_of!! + retval(i, j) = retval.index_of (retval(i, j)); + } + else + retval(i, j) = retval.index_of (retval(i, j)); + } + return retval; +} + +galois +galois::exp (void) const +{ + bool warned = false; + if (!have_field ()) + { + gripe_invalid_galois (); + return galois (); + } + + galois retval (*this); + int nr = rows (); + int nc = cols (); + + for (int j = 0; j < nc; j++) + for (int i = 0; i < nr; i++) + { + if (retval(i, j) == n ()) + { + if (!warned) + { + warning ("warning: exp of 2^m-1 undefined in Galois field"); + warned = true; + } + // How do I flag a NaN without either + // 1) Having to check everytime that the data is valid + // 2) Causing overflow in alpha_to or index_of!! + retval(i, j) = retval.alpha_to (retval(i, j)); + } + else + retval(i, j) = retval.alpha_to (retval(i, j)); + } + return retval; +} + +template class base_lu ; + +void +galoisLU::factor (const galois& a, const pivot_type& typ) +{ + int a_nr = a.rows (); + int a_nc = a.cols (); + int mn = (a_nr > a_nc ? a_nc : a_nr); + + ptype = typ; + info = 0; + ipvt.resize (dim_vector (mn, 1)); + + a_fact = a; + + for (int j = 0; j < mn; j++) + { + int jp = j; + + // Find the pivot and test for singularity + if (ptype == galoisLU::ROW) + { + for (int i = j+1; i < a_nr; i++) + if (a_fact(i, j) > a_fact(jp, j)) + jp = i; + } + else + { + for (int i = j+1; i < a_nc; i++) + if (a_fact(j, i) > a_fact(j, jp)) + jp = i; + } + + ipvt(j) = jp; + + if (a_fact(jp, j) != 0) + { + if (ptype == galoisLU::ROW) + { + // Apply the interchange to columns 1:NC. + if (jp != j) + for (int i = 0; i < a_nc; i++) + { + int tmp = a_fact(j, i); + a_fact(j, i) = a_fact(jp, i); + a_fact(jp, i) = tmp; + } + } + else + { + // Apply the interchange to rows 1:NR. + if (jp != j) + for (int i = 0; i < a_nr; i++) + { + int tmp = a_fact(i, j); + a_fact(i, j) = a_fact(i, jp); + a_fact(i, jp) = tmp; + } + } + + // Compute elements J+1:M of J-th column. + if ( j < a_nr-1) + { + int idxj = a_fact.index_of (a_fact(j, j)); + for (int i = j+1; i < a_nr; i++) + { + if (a_fact(i, j) == 0) + a_fact(i, j) = 0; + else + a_fact(i, j) = a_fact.alpha_to (modn (a_fact.index_of (a_fact(i, j)) + - idxj + a_fact.n (), a_fact.m (), + a_fact.n ())); + } + } + } + else + { + info = 1; + } + + if (j < mn-1) + { + // Update trailing submatrix. + for (int i = j+1; i < a_nr; i++) + { + if (a_fact(i, j) != 0) + { + int idxi = a_fact.index_of (a_fact(i, j)); + for (int k = j+1; k < a_nc; k++) + { + if (a_fact(j, k) != 0) + a_fact(i, k) ^= a_fact.alpha_to (modn (a_fact.index_of (a_fact(j, k)) + + idxi, a_fact.m (), + a_fact.n ())); + } + } + } + } + } +} + +galois +galoisLU::L (void) const +{ + int a_nr = a_fact.rows (); + int a_nc = a_fact.cols (); + int mn = (a_nr < a_nc ? a_nr : a_nc); + + galois l (a_nr, mn, 0, a_fact.m (), a_fact.primpoly ()); + + for (int i = 0; i < mn; i++) + l(i, i) = 1; + + for (int j = 0; j < mn; j++) + for (int i = j+1; i < a_nr; i++) + l(i, j) = a_fact (i, j); + + return l; +} + +galois +galoisLU::U (void) const +{ + int a_nr = a_fact.rows (); + int a_nc = a_fact.cols (); + int mn = (a_nr < a_nc ? a_nr : a_nc); + + galois u (mn, a_nc, 0, a_fact.m (), a_fact.primpoly ()); + + for (int j = 0; j < a_nc; j++) + for (int i = 0; i < (j+1 > mn ? mn : j+1); i++) + u (i, j) = a_fact (i, j); + return u; +} + +galois +galois::inverse (void) const +{ + int info; + return inverse (info); +} + +galois +galois::inverse (int& info, int force) const +{ + int nr = rows (); + int nc = cols (); + info = 0; + + if (nr != nc || nr == 0 || nc == 0) + { + (*current_liboctave_error_handler) ("inverse requires square matrix"); + return galois (); + } + else + { + int info = 0; + + // Solve with identity matrix to find the inverse. + galois btmp (nr, nr, 0, m (), primpoly ()); + for (int i = 0; i < nr; i++) + btmp(i, i) = 1; + + galois retval = solve (btmp, info, 0); + + if (info == 0) + return retval; + else + return galois (); + } +} + +galois +galois::determinant (void) const +{ + int info; + return determinant (info); +} + +galois +galois::determinant (int& info) const +{ + galois retval (1, 1, 0, m (), primpoly ()); + + int nr = rows (); + int nc = cols (); + info = -1; + + if (nr == 0 || nc == 0) + { + info = 0; + retval(0, 0) = 1; + } + else + { + galoisLU fact (*this); + + if ( ! fact.singular ()) + { + galois A (fact.a_fact); + info = 0; + + retval(0, 0) = A(0, 0); + for (int i = 1; i < nr; i++) + { + if ((retval(0, 0) == 0) || (A(i, i) == 0)) + { + retval(0, 0) = 0; + error ("What the hell are we doing here!!!"); + } + else + retval(0, 0) = alpha_to (modn (index_of (retval(0, 0)) + + index_of (A(i, i)), m (), n ())); + } + } + } + + return retval; +} + +galois +galois::solve (const galois& b) const +{ + int info; + return solve (b, info); +} + +galois +galois::solve (const galois& b, int& info) const +{ + return solve (b, info, 0); +} + +galois +galois::solve (const galois& b, int& info, + solve_singularity_handler sing_handler) const +{ + galois retval (b); + + if (!have_field () || !b.have_field ()) + { + gripe_invalid_galois (); + return galois (); + } + else if ((m () != b.m ()) || (primpoly () != b.primpoly ())) + { + gripe_differ_galois (); + return galois (); + } + + int nr = rows (); + int nc = cols (); + int b_nr = b.rows (); + int b_nc = b.cols (); + galois c (nr, 1, 0, m (), primpoly ()); + + // if (nr == 0 || nc == 0 || nr != nc || nr != b_nr) + if (nr == 0 || nc == 0 || nr != b_nr) + { + (*current_liboctave_error_handler) + ("matrix dimension mismatch solution of linear equations"); + return galois (); + } + else if (nc > nr) + { + // Under-determined system, use column interchanges. + galoisLU fact ((*this), galoisLU::COL); + + if (fact.singular ()) + { + info = -1; + if (sing_handler) + sing_handler (0.0); + else + (*current_liboctave_error_handler)("galois matrix singular"); + + return galois (); + } + else + { + galois A (fact.a_fact); + Array IP (fact.ipvt); + + // Resize the number of solution rows if needed + if (nc > nr) + retval.resize (dim_vector (b_nr+nc-nr, b_nc), 0); + + //Solve L*X = B, overwriting B with X. + int mn = (nc < nr ? nc : nr); + for (int k = 0; k < mn; k++) + { + for (int i = k+1; i < nr; i++) + c(i, 0) = index_of (A(i, k)); + + for (int j = 0; j < b_nc; j++) + if (retval(k, j) != 0) + { + int idx = index_of (retval(k, j)); + for (int i = k+1; i < nr; i++) + if (A(i, k) != 0) + retval(i, j) ^= alpha_to (modn (c(i, 0) + idx, m (), n ())); + } + } + + // Solve U*X = B, overwriting B with X. + for (int k = (nc < nr ? nc-1 : nr-1); k >= 0; k--) + { + int mn = k+1 < nr ? k+1 : nr; + for (int i = 0; i < mn; i++) + c(i, 0) = index_of (A(i, k)); + mn = k < nr ? k : nr; + for (int j = 0; j < b_nc; j++) + if (retval(k, j) != 0) + { + retval(k, j) = alpha_to (modn (index_of (retval(k, j)) - + c(k, 0) + n (), m (), n ())); + int idx = index_of (retval(k, j)); + for (int i = 0; i < mn; i++) + if (A(i, k) != 0) + retval(i, j) ^= alpha_to (modn (c(i, 0) + idx, m (), n ())); + } + } + + // Apply row interchanges to the right hand sides. + //for (int j = 0; j < IP.length (); j++) + for (int j = IP.numel ()-1; j >= 0; j--) + { + int piv = IP(j); + for (int i = 0; i < b_nc; i++) + { + int tmp = retval(j, i); + retval(j, i) = retval(piv, i); + retval(piv, i) = tmp; + } + } + } + } + else + { + galoisLU fact (*this); + + if (fact.singular ()) + { + info = -1; + if (sing_handler) + sing_handler (0.0); + else + (*current_liboctave_error_handler)("galois matrix singular"); + + return galois (); + } + else + { + galois A (fact.a_fact); + Array IP (fact.ipvt); + + // Apply row interchanges to the right hand sides. + for (int j = 0; j < IP.numel (); j++) + { + int piv = IP(j); + for (int i = 0; i < b_nc; i++) + { + int tmp = retval(j, i); + retval(j, i) = retval(piv, i); + retval(piv, i) = tmp; + } + } + + //Solve L*X = B, overwriting B with X. + int mn = (nc < nr ? nc : nr); + for (int k = 0; k < mn; k++) + { + for (int i = k+1; i < nr; i++) + c(i, 0) = index_of (A(i, k)); + for (int j = 0; j < b_nc; j++) + if (retval(k, j) != 0) + { + int idx = index_of (retval(k, j)); + for (int i = k+1; i < nr; i++) + if (A(i, k) != 0) + retval(i, j) ^= alpha_to (modn (c(i, 0) + idx, m (), n ())); + } + } + + // Solve U*X = B, overwriting B with X. + for (int k = (nc < nr ? nc-1 : nr-1); k >= 0; k--) + { + int mn = k+1 < nr ? k+1 : nr; + for (int i = 0; i < mn; i++) + c(i, 0) = index_of (A(i, k)); + mn = k < nr ? k : nr; + for (int j = 0; j < b_nc; j++) + if (retval(k, j) != 0) + { + retval(k, j) = alpha_to (modn (index_of (retval(k, j)) - + c(k, 0) + n (), m (), n ())); + int idx = index_of (retval(k, j)); + for (int i = 0; i < mn; i++) + if (A(i, k) != 0) + retval(i, j) ^= alpha_to (modn (c(i, 0) + idx, m (), n ())); + } + } + + // Resize the number of solution rows if needed + if (nc < nr) + retval.resize (dim_vector (b_nr+nc-nr, b_nc)); + + } + } + + return retval; +} + +galois +xdiv (const galois& a, const Matrix& b) +{ + galois btmp (b, a.m (), a.primpoly ()); + + return xdiv (a, btmp); +} + +galois +xdiv (const Matrix& a, const galois& b) +{ + galois atmp (a, b.m (), b.primpoly ()); + + return xdiv (atmp, b); +} + +galois +xdiv (const galois& a, const galois& b) +{ + int info = 0; + int a_nc = a.cols (); + int b_nc = b.cols (); + + // if ((a_nc != b_nc) || (b.rows () != b.cols ())) + if (a_nc != b_nc) + { + int a_nr = a.rows (); + int b_nr = b.rows (); + + OCTAVE__ERR_NONCONFORMANT ("operator /", a_nr, a_nc, b_nr, b_nc); + return galois (); + } + + galois atmp = a.transpose (); + galois btmp = b.transpose (); + galois result = btmp.solve (atmp, info, 0); + + if (info == 0) + return galois (result.transpose ()); + else + return galois (); +} + + +galois +xleftdiv (const galois& a, const Matrix& b) +{ + galois btmp (b, a.m (), a.primpoly ()); + + return xleftdiv (a, btmp); +} + +galois +xleftdiv (const Matrix& a, const galois& b) +{ + galois atmp (a, b.m (), b.primpoly ()); + + return xleftdiv (atmp, b); +} + +galois +xleftdiv (const galois& a, const galois& b) +{ + int info = 0; + int a_nr = a.rows (); + int b_nr = b.rows (); + + // if ((a_nr != b_nr) || (a.rows () != a.columns ())) + if (a_nr != b_nr) + { + int a_nc = a.cols (); + int b_nc = b.cols (); + + OCTAVE__ERR_NONCONFORMANT ("operator \\", a_nr, a_nc, b_nr, b_nc); + return galois (); + } + + galois result = a.solve (b, info, 0); + + if (info == 0) + return result; + else + return galois (); +} + +MM_BIN_OPS1 (galois, galois, galois, 1, 2, GALOIS) +MM_BIN_OPS1 (galois, galois, Matrix, 1, 2, MATRIX) +MM_BIN_OPS1 (galois, Matrix, galois, 2, 1, MATRIX) + +MM_CMP_OPS1 (galois, , galois, , 1, 2, GALOIS) +MM_CMP_OPS1 (galois, , Matrix, , 1, 2, MATRIX) +MM_CMP_OPS1 (Matrix, , galois, , 2, 1, MATRIX) + +MM_BOOL_OPS1 (galois, galois, 0.0, 1, 2, GALOIS) +MM_BOOL_OPS1 (galois, Matrix, 0.0, 1, 2, MATRIX) +MM_BOOL_OPS1 (Matrix, galois, 0.0, 2, 1, MATRIX) + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/galois.h b/src/galois.h new file mode 100644 index 0000000..cfcbec5 --- /dev/null +++ b/src/galois.h @@ -0,0 +1,209 @@ +//Copyright (C) 2003 David Bateman +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of the +// License, or (at your option) any later version. +// +// This program 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 +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, see +// . +// +// In addition to the terms of the GPL, you are permitted to link this +// program with any Open Source program, as defined by the Open Source +// Initiative (www.opensource.org) + +#if !defined (octave_galois_int_h) +#define octave_galois_int_h 1 + +#include +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include + +#ifdef HAVE_OCTAVE_BASE_LU_H +# include +#else +# include "base-lu.h" +#endif + +#include "galoisfield.h" + +typedef void (*solve_singularity_handler) (double rcond); + +class +galois : public MArray +{ +public: + galois (void) : field (NULL) { } + galois (const Array& a, const int& m=1, const int& primpoly=0); + galois (const MArray& a, const int& m=1, const int& primpoly=0); + galois (const Matrix& a, const int& m=1, const int& primpoly=0); + galois (int nr, int nc, const int& val=0, const int& _m=1, + const int& _primpoly=0); + galois (int nr, int nc, double val=0., const int& _m=1, + const int& _primpoly=0); + galois (const galois& a); + ~galois (void); + + galois index (idx_vector& i, int resize_ok = 0, const int& rfv = 0) const; + + galois index (idx_vector& i, idx_vector& j, int resize_ok = 0, + const int& rfv = 0) const; + + // unary operations + + boolMatrix operator ! (void) const; + + galois transpose (void) const; + + // other operations + boolMatrix all (int dim = -1) const; + boolMatrix any (int dim = -1) const; + + galois concat (const galois& rb, const Array& ra_idx); + galois concat (const Matrix& rb, const Array& ra_idx); + friend galois concat (const Matrix& ra, const galois& rb, + const Array& ra_idx); + + galois& insert (const galois& a, int r, int c); + + galois diag (void) const; + galois diag (int k) const; + + galois prod (int dim) const; + galois sum (int dim) const; + galois sumsq (int dim) const; + galois sqrt (void) const; + galois log (void) const; + galois exp (void) const; + galois inverse (void) const; + galois inverse (int &info, int force = 0) const; + galois solve (const galois& b) const; + galois solve (const galois& b, int& info) const; + galois solve (const galois& b, int& info, + solve_singularity_handler sing_handler) const; + + galois determinant (void) const; + galois determinant (int& info) const; + + galois &operator = (const galois& t); + galois &operator += (const galois& a); + galois &operator -= (const galois& a); + +private: + // Pointer to the Galois field structure used + galois_field_node *field; + +public: + // Is the variable initialized?? + bool have_field (void) const { return (field ? true : false); }; + + // Access to Galois field structures + int m (void) const { return (field->m); } + int primpoly (void) const { return (field->primpoly); } + + int n (void) const { return (field->n); } + int alpha_to (const int& idx) const { return (field->alpha_to (idx)); } + int index_of (const int& idx) const { return (field->index_of (idx)); } +}; + +class +galoisLU : public base_lu +{ + friend class galois; +public: + + enum pivot_type + { + ROW, + COL + }; + + galoisLU (void) : base_lu () { } + + galoisLU (const galois& a, const pivot_type& typ) { factor (a, typ); } + + galoisLU (const galois& a) { factor (a, galoisLU::ROW); } + + galoisLU (const galoisLU& a) : base_lu (a) { } + + galoisLU& operator = (const galoisLU& a) + { + if (this != &a) + base_lu :: operator = (a); + + return *this; + } + + ~galoisLU (void) { } + + galois L (void) const; + + galois U (void) const; + + bool singular (void) const { return info != 0; } + + pivot_type type (void) const { return ptype; } +private: + void factor (const galois& a, const pivot_type& typ); + + int info; + + pivot_type ptype; +}; + +#ifndef DEFMETHOD_DLD +void install_gm_gm_ops (void); +void install_gm_m_ops (void); +void install_m_gm_ops (void); +void install_gm_s_ops (void); +void install_s_gm_ops (void); +void install_fil_gm_ops (void); +#else +void install_gm_gm_ops (octave::type_info& ti); +void install_gm_m_ops (octave::type_info& ti); +void install_m_gm_ops (octave::type_info& ti); +void install_gm_s_ops (octave::type_info& ti); +void install_s_gm_ops (octave::type_info& ti); +void install_fil_gm_ops (octave::type_info& ti); +#endif + +galois elem_pow (const galois& a, const galois& b); +galois elem_pow (const galois& a, const Matrix& b); +galois elem_pow (const galois& a, double b); +galois elem_pow (const galois& a, int b); + +galois pow (const galois& a, const galois& b); +galois pow (const galois& a, double b); +galois pow (const galois& a, int b); + +galois xdiv (const galois& a, const galois& b); +galois xdiv (const galois& a, const Matrix& b); +galois xdiv (const Matrix& a, const galois& b); +galois xleftdiv (const galois& a, const galois& b); +galois xleftdiv (const galois& a, const Matrix& b); +galois xleftdiv (const Matrix& a, const galois& b); + +galois operator * (const galois& a, const galois& b); +galois operator * (const galois& a, const Matrix& b); +galois operator * (const Matrix& a, const galois& b); + +MM_OP_DECLS (galois, galois, galois, ); +MM_OP_DECLS (galois, galois, Matrix, ); +MM_OP_DECLS (galois, Matrix, galois, ); + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/galoisfield.cc b/src/galoisfield.cc new file mode 100644 index 0000000..5697ca3 --- /dev/null +++ b/src/galoisfield.cc @@ -0,0 +1,217 @@ +//Copyright (C) 2003 David Bateman +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of the +// License, or (at your option) any later version. +// +// This program 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 +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, see +// . +// +// In addition to the terms of the GPL, you are permitted to link this +// program with any Open Source program, as defined by the Open Source +// Initiative (www.opensource.org) + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "galois.h" +#include "galoisfield.h" +#include "galois-def.h" + +// The default primitive polynomials for GF(2^(indx+1)) +int default_galois_primpoly[] = { 0x3, 0x7, 0xb, 0x13, 0x25, + 0x43, 0x89, 0x11d, 0x211, 0x409, + 0x805, 0x1053, 0x201b, 0x4443, 0x8003, + 0x1100b}; + +galois_field_node::galois_field_node (void) : + m (0), + primpoly (0), + n (0), + next (NULL), + prev (NULL), + count (0) { } + +galois_field_node::galois_field_node (const int& _m, const int& _primpoly) +{ + int mask; + + next = NULL; + prev = NULL; + count = 0; // Flag that field is currently bad... + + // Initialize order of GF(2^m) + m = _m; + if ((m < 1) || (m > __OCTAVE_GALOIS_MAX_M)) + { + gripe_order_galois (m); + return; + } + n = (1< n) + { + gripe_irred_galois (primpoly); + return; + } + + count = 1; // Field is good now !! + return; +} + +galois_field_node & galois_field_node::operator = (const galois_field_node &t) +{ + m = t.m; + primpoly = t.primpoly; + n = t.n; + alpha_to = t.alpha_to; + index_of = t.index_of; + next = NULL; + prev = NULL; + count = 1; + return *this; +} + +galois_field_list::~galois_field_list (void) +{ + while (first) + { + galois_field_node * tmp = first->next; + delete first; + first = tmp; + } +} + +galois_field_node* +galois_field_list::find_galois_field (const int& m, const int& primpoly) +{ + galois_field_node* ptr = first; + + while (ptr) + { + if ((ptr->m == m) && (ptr->primpoly == primpoly)) + return ptr; + ptr = ptr->next; + } + return NULL; +} + +galois_field_node* +galois_field_list::create_galois_field (const int& m, const int& primpoly) +{ + galois_field_node* ptr = find_galois_field (m, primpoly); + + if (ptr) + { + // We already have this field. Bump counter and return + ptr->count++; + return ptr; + } + + // Create a new field and add it to the list + ptr = new galois_field_node (m, primpoly); + if (ptr->count == 0) + { + gripe_init_galois (); + return ptr; + } + if (first) + { + ptr->next = first; + first->prev = ptr; + } + else + last = ptr; + first = ptr; + + return ptr; +} + +int +galois_field_list::delete_galois_field (galois_field_node* field) +{ + if (!field) + return 0; + + field->count--; + if (field->count == 0) + { + if (field == first) + { + first = field->next; + if (first) + first->prev = NULL; + } + else if (field == last) + { + last = field->prev; + if (last) + last->next = NULL; + } + else + { + field->prev->next = field->next; + field->next->prev = field->prev; + } + delete field; + return 1; + } + else + return 0; +} + +/* + ;;; Local Variables: *** + ;;; mode: C++ *** + ;;; End: *** +*/ diff --git a/src/galoisfield.h b/src/galoisfield.h new file mode 100644 index 0000000..08b0408 --- /dev/null +++ b/src/galoisfield.h @@ -0,0 +1,86 @@ +//Copyright (C) 2003 David Bateman +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of the +// License, or (at your option) any later version. +// +// This program 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 +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, see +// . +// +// In addition to the terms of the GPL, you are permitted to link this +// program with any Open Source program, as defined by the Open Source +// Initiative (www.opensource.org) + +#if !defined (octave_galois_field_int_h) +#define octave_galois_field_int_h 1 + +#include + +// Maximum value of m +#define __OCTAVE_GALOIS_MAX_M 16 + +// Maximum value of m. If you change the above, change here also +#define __OCTAVE_GALOIS_MAX_M_AS_STRING "16" + +// A0 flag -inf value +#define __OCTAVE_GALOIS_A0 (n) + +// The default primitive polynomials for GF(2^(indx+1)) +extern int default_galois_primpoly[]; + +class +galois_field_node +{ + friend class galois_field_list; + friend class galois; + +private: + int m; + int primpoly; + int n; + MArray alpha_to; + MArray index_of; + + galois_field_node *next; + galois_field_node *prev; + + int count; + +public: + galois_field_node (void); + galois_field_node (const int& _m = 1, const int& _primpoly = 0); + galois_field_node & operator = (const galois_field_node &t); +}; + +class +galois_field_list +{ +private: + galois_field_node *first; + galois_field_node *last; + +public: + galois_field_list (void) : first (NULL), last (NULL) { } + + ~galois_field_list (void); + + galois_field_node * find_galois_field (const int& m, const int& primpoly); + galois_field_node * create_galois_field (const int& m, const int& primpoly); + int delete_galois_field (galois_field_node *field); + +}; + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/genqamdemod.cc b/src/genqamdemod.cc new file mode 100644 index 0000000..2ecdee4 --- /dev/null +++ b/src/genqamdemod.cc @@ -0,0 +1,120 @@ +//Copyright (C) 2006 Charalampos C. Tsimenidis +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of the +// License, or (at your option) any later version. +// +// This program 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 +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, see +// . + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +DEFUN_DLD (genqamdemod, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{y} =} genqamdemod (@var{x}, @var{C})\n\ +General quadrature amplitude demodulation. The complex envelope\n\ +quadrature amplitude modulated signal @var{x} is demodulated using a\n\ +constellation mapping specified by the 1D vector @var{C}.\n\ +@end deftypefn") +{ + octave_value retval; + int i, j, m; + double tmp1, tmp2; + + if (args.length () != 2) + { + print_usage (); + return retval; + } + + int nr1 (args(0).rows ()); + int nc1 (args(0).columns ()); + int arg_is_empty1 = args(0).OV_ISEMPTY(); + Matrix y (nr1,nc1); + + int nr2 (args(1).rows ()); + int nc2 (args(1).columns ()); + int M = (nr2>nc2)?nr2:nc2; + + if (arg_is_empty1 < 0) + return retval; + if (arg_is_empty1 > 0) + return octave_value (Matrix ()); + + if (args(0).OV_ISREAL () && args(1).OV_ISREAL ()) + { // Real-valued signal & constellation + Matrix x (args(0).matrix_value ()); + ColumnVector constellation (args(1).vector_value ()); + for (i = 0;i < nr1;i++) + { + for (j = 0;j < nc1;j++) + { + tmp1 = fabs (x(i,j)-constellation(0)); + y(i,j) = 0; + for (m = 1; m < M;m++) + { + tmp2 = fabs (x(i,j)-constellation(m)); + if (tmp2 < tmp1) + { + y(i,j) = m; + tmp1 = tmp2; + } + } + } + } + } + else if (args(0).OV_ISCOMPLEX () || args(1).OV_ISCOMPLEX ()) + { // Complex-valued input & constellation + ComplexMatrix x (args(0).complex_matrix_value ()); + ComplexColumnVector constellation (args(1).complex_vector_value ()); + if (!error_state) + { + for (i = 0;i < nr1;i++) + { + for (j = 0;j < nc1;j++) + { + tmp1 = abs (x(i,j)-constellation(0)); + y(i,j) = 0; + for (m = 1;m < M;m++) + { + tmp2 = abs (x(i,j)-constellation(m)); + if (tmp2 < tmp1) + { + y(i,j) = m; + tmp1 = tmp2; + } + } + } + } + } + else + print_usage (); + } + else + { + print_usage (); + } + return retval = y; +} + +/* +%!assert (genqamdemod ([-7:2:7], [-7:2:7]), [0:7]) +%!assert (genqamdemod ([-7 -5 -1 -3 7 5 1 3], [-7 -5 -1 -3 7 5 1 3]), [0:7]) + +%% Test input validation +%!error genqamdemod () +%!error genqamdemod (1) +%!error genqamdemod (1, 2, 3) +*/ diff --git a/src/gf.cc b/src/gf.cc new file mode 100644 index 0000000..c568cda --- /dev/null +++ b/src/gf.cc @@ -0,0 +1,2843 @@ +// Copyright (C) 1994-1997 Robert Morelos-Zaragoza +// Copyright (C) 2002 Phil Karn +// Copyright (C) 2003 David Bateman +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of the +// License, or (at your option) any later version. +// +// This program 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 +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, see +// . +// +// In addition to the terms of the GPL, you are permitted to link this +// program with any Open Source program, as defined by the Open Source +// Initiative (www.opensource.org) + +/* +Part of the function rsenc and the function decode_rs are from Phil Karn. See +the website http://www.ka9q.net/code/fec for more details. + +Parts of the function bchenco and bchdeco are from Robert Morelos-Zaragoza. See +the website http://www.eccpage.com for more details. Permission has been granted +for a GPL release of his code +*/ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#ifdef HAVE_OCTAVE_INTERPRETER_H +#include +#endif +#include +#ifdef HAVE_OCTAVE_GRIPES_H +#include +#define OCTAVE__ERR_SQUARE_MATRIX_REQUIRED(a) gripe_square_matrix_required(a) +#endif +#ifdef HAVE_OCTAVE_ERRWARN_H +#include +#define OCTAVE__ERR_SQUARE_MATRIX_REQUIRED(a) err_square_matrix_required(a, "") +#endif + +#include +#include +#include +#include + +#include "galois.h" +#include "ov-galois.h" + +static bool galois_type_loaded = false; + +// PKG_ADD: autoload ("isgalois", "gf.oct"); +// PKG_DEL: autoload ("isgalois", "gf.oct", "remove"); +DEFUN_DLD (isgalois, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} isgalois (@var{expr})\n\ +Return 1 if the value of the expression @var{expr} is a Galois Field.\n\ +@end deftypefn") +{ + if (args.length () != 1) + print_usage (); + else if (!galois_type_loaded) + // Can be of Galois type if the type isn't load :-/ + return octave_value (0.); + else + return octave_value (args(0).type_id () == + octave_galois::static_type_id ()); + return octave_value (); +} + +/* +%% Test input validation +%!error isgalois () +%!error isgalois (1, 2) +*/ + +// FIXME: +// I want to replace the "16" below with __OCTAVE_GALOIS_MAX_M_AS_STRING, +// but as I don't run the preprocessor when getting the help from the +// functions, this can't be done at the point. So if more default primitive +// polynomials are added to galoisfield.cc, need to update the "16" here +// as well!! +#ifdef DEFMETHOD_DLD +DEFMETHOD_DLD (gf, interp, args, nargout, +#else +DEFUN_DLD (gf, args, nargout, +#endif + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{y} =} gf (@var{x})\n\ +@deftypefnx {Loadable Function} {@var{y} =} gf (@var{x}, @var{m})\n\ +@deftypefnx {Loadable Function} {@var{y} =} gf (@var{x}, @var{m}, @var{primpoly})\n\ +Creates a Galois field array GF(2^@var{m}) from the matrix @var{x}. The\n\ +Galois field has 2^@var{m} elements, where @var{m} must be between 1 and 16.\n\ +The elements of @var{x} must be between 0 and 2^@var{m} - 1. If @var{m} is\n\ +undefined it defaults to the value 1.\n\ +\n\ +The primitive polynomial to use in the creation of Galois field can be\n\ +specified with the @var{primpoly} variable. If this is undefined a default\n\ +primitive polynomial is used. It should be noted that the primitive\n\ +polynomial must be of the degree @var{m} and it must be irreducible.\n\ +\n\ +The output of this function is recognized as a Galois field by Octave and\n\ +other matrices will be converted to the same Galois field when used in an\n\ +arithmetic operation with a Galois field.\n\ +\n\ +@seealso{isprimitive, primpoly}\n\ +@end deftypefn") +{ + Matrix data; + octave_value retval; + int nargin = args.length (); + int m = 1; + int primpoly = 0; + + if (nargin < 1 || nargin > 3) + { + print_usage (); + return retval; + } + + data = args(0).matrix_value (); + if (nargin > 1) + m = args(1).int_value (); + if (nargin > 2) + primpoly = args(2).int_value (); + + if (!galois_type_loaded) + { + octave_galois::register_type (); +#ifndef DEFMETHOD_DLD + install_gm_gm_ops (); + install_m_gm_ops (); + install_gm_m_ops (); + install_s_gm_ops (); + install_gm_s_ops (); + galois_type_loaded = true; + + mlock (); +#else + interp.mlock (); + octave::type_info& ti = interp.get_type_info (); + + install_gm_gm_ops (ti); + install_m_gm_ops (ti); + install_gm_m_ops (ti); + install_s_gm_ops (ti); + install_gm_s_ops (ti); + galois_type_loaded = true; +#endif + } + + retval = new octave_galois (data, m, primpoly); + return retval; +} + +/* +%% Test input validation +%!error gf () +%!error gf (1, 2, 3, 4) +*/ + +static octave_value +make_gdiag (const octave_value& a, const octave_value& b) +{ + octave_value retval; + + if ((!galois_type_loaded) || (a.type_id () != + octave_galois::static_type_id ())) + OCTAVE__ERR_WRONG_TYPE_ARG ("gdiag", a); + else + { + galois m = ((const octave_galois&) a.get_rep ()).galois_value (); + int k = b.nint_value (); + + if (! error_state) + { + int nr = m.rows (); + int nc = m.columns (); + + if (nr == 0 || nc == 0) + retval = new octave_galois (m); + else if (nr == 1 || nc == 1) + { + int roff = 0; + int coff = 0; + if (k > 0) + { + roff = 0; + coff = k; + } + else if (k < 0) + { + k = -k; + roff = k; + coff = 0; + } + + if (nr == 1) + { + int n = nc + k; + galois r (n, n, 0, m.m (), m.primpoly ()); + for (int i = 0; i < nc; i++) + r (i+roff, i+coff) = m (0, i); + retval = new octave_galois (r); + } + else + { + int n = nr + k; + galois r (n, n, 0, m.m (), m.primpoly ()); + for (int i = 0; i < nr; i++) + r (i+roff, i+coff) = m (i, 0); + retval = new octave_galois (r); + } + } + else + { + galois r = m.diag (k); + if (r.numel () > 0) + retval = new octave_galois (r); + } + } + else + OCTAVE__ERR_WRONG_TYPE_ARG ("gdiag", a); + } + return retval; +} + +// PKG_ADD: autoload ("gdiag", "gf.oct"); +// PKG_DEL: autoload ("gdiag", "gf.oct", "remove"); +DEFUN_DLD (gdiag, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} gdiag (@var{v}, @var{k})\n\ +Return a diagonal matrix with Galois vector @var{v} on diagonal @var{k}.\n\ +The second argument is optional. If it is positive, the vector is placed on\n\ +the @var{k}-th super-diagonal. If it is negative, it is placed on the\n\ +@var{-k}-th sub-diagonal. The default value of @var{k} is 0, and the\n\ +vector is placed on the main diagonal. For example,\n\ +\n\ +@example\n\ +gdiag (gf ([1, 2, 3], 2), 1)\n\ +ans =\n\ +GF(2^2) array. Primitive Polynomial = D^2+D+1 (decimal 7)\n\ +\n\ +Array elements =\n\ +\n\ + 0 1 0 0\n\ + 0 0 2 0\n\ + 0 0 0 3\n\ + 0 0 0 0\n\ +\n\ +@end example\n\ +@seealso{diag}\n\ +@end deftypefn") +{ + octave_value retval; + + int nargin = args.length (); + + if (nargin == 1 && args(0).is_defined ()) + retval = make_gdiag (args(0), octave_value (0.)); + else if (nargin == 2 && args(0).is_defined () && args(1).is_defined ()) + retval = make_gdiag (args(0), args(1)); + else + print_usage (); + + return retval; +} + +/* +%% Test input validation +%!error gdiag () +%!error gdiag (1, 2, 3) +*/ + +// PKG_ADD: autoload ("greshape", "gf.oct"); +// PKG_DEL: autoload ("greshape", "gf.oct", "remove"); +DEFUN_DLD (greshape, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} greshape (@var{a}, @var{m}, @var{n})\n\ +Return a matrix with @var{m} rows and @var{n} columns whose elements are\n\ +taken from the Galois array @var{a}. To decide how to order the elements,\n\ +Octave pretends that the elements of a matrix are stored in column-major\n\ +order (like Fortran arrays are stored).\n\ +\n\ +For example,\n\ +\n\ +@example\n\ +greshape (gf ([1, 2, 3, 4], 3), 2, 2)\n\ +ans =\n\ +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11)\n\ +\n\ +Array elements =\n\ +\n\ + 1 3\n\ + 2 4\n\ +\n\ +@end example\n\ +\n\ +The @code{greshape} function is equivalent to\n\ +\n\ +@example\n\ +@group\n\ +retval = gf (zeros (m, n), a.m, a.prim_poly);\n\ +retval(:) = a;\n\ +@end group\n\ +@end example\n\ +\n\ +@noindent\n\ +but it is somewhat less cryptic to use @code{reshape} instead of the\n\ +colon operator. Note that the total number of elements in the original\n\ +matrix must match the total number of elements in the new matrix.\n\ +@seealso{reshape, :}\n\ +@end deftypefn") +{ + octave_value retval; + int nargin = args.length (); + + if (nargin != 2 && nargin != 3) + { + print_usage (); + } + else + { + int mr = 0, mc = 0; + + if ((!galois_type_loaded) || (args(0).type_id () != + octave_galois::static_type_id ())) + { + OCTAVE__ERR_WRONG_TYPE_ARG ("greshape", args(0)); + return retval; + } + galois a = ((const octave_galois&) args(0).get_rep ()).galois_value (); + + if (nargin == 2) + { + RowVector tmp = args(1).row_vector_value (); + mr = (int)tmp(0); + mc = (int)tmp(1); + } + else if (nargin == 3) + { + mr = args(1).nint_value (); + mc = args(2).nint_value (); + } + + int nr = a.rows (); + int nc = a.cols (); + if ((nr * nc) != (mr * mc)) + error ("greshape: sizes must match"); + else + { + RowVector tmp1 (mr*mc); + for (int i = 0; i < nr; i++) + for (int j = 0; j < nc; j++) + tmp1(i+j*nr) = (double)a(i, j); + galois tmp2 (mr, mc, 0, a.m (), a.primpoly ()); + for (int i = 0; i < mr; i++) + for (int j = 0; j < mc; j++) + tmp2(i, j) = (int)tmp1(i+j*mr); + retval = new octave_galois (tmp2); + } + } + return retval; +} + +/* +%% Test input validation +%!error greshape () +%!error greshape (1) +%!error greshape (1, 2, 3, 4) +*/ + +#define DATA_REDUCTION(FCN) \ + \ + octave_value_list retval; \ + \ + int nargin = args.length (); \ + \ + if (nargin == 1 || nargin == 2) \ + { \ + octave_value arg = args(0); \ + \ + int dim = (nargin == 1 ? -1 : args(1).int_value (true) - 1); \ + \ + if (! error_state) \ + { \ + if (dim <= 1 && dim >= -1) \ + { \ + if (galois_type_loaded && (arg.type_id () == \ + octave_galois::static_type_id ())) \ + { \ + galois tmp = ((const octave_galois&)arg.get_rep ()).galois_value (); \ + \ + if (! error_state) \ + retval(0) = new octave_galois (tmp.FCN (dim)); \ + } \ + else \ + { \ + OCTAVE__ERR_WRONG_TYPE_ARG (#FCN, arg); \ + return retval; \ + } \ + } \ + else \ + error (#FCN ": invalid dimension argument = %d", dim + 1); \ + } \ + } \ + else \ + print_usage (); \ + \ + return retval + +// PKG_ADD: autoload ("gprod", "gf.oct"); +// PKG_DEL: autoload ("gprod", "gf.oct", "remove"); +DEFUN_DLD (gprod, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} gprod (@var{x}, @var{dim})\n\ +Product of elements along dimension @var{dim} of Galois array. If\n\ +@var{dim} is omitted, it defaults to 1 (column-wise products).\n\ +@seealso{prod}\n\ +@end deftypefn") +{ + DATA_REDUCTION (prod); +} + +/* +%% Test input validation +%!error gprod () +%!error gprod (1, 2, 3) +*/ + +// PKG_ADD: autoload ("gsum", "gf.oct"); +// PKG_DEL: autoload ("gsum", "gf.oct", "remove"); +DEFUN_DLD (gsum, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} gsum (@var{x}, @var{dim})\n\ +Sum of elements along dimension @var{dim} of Galois array. If @var{dim}\n\ +is omitted, it defaults to 1 (column-wise sum).\n\ +@seealso{sum}\n\ +@end deftypefn") +{ + DATA_REDUCTION (sum); +} + +/* +%% Test input validation +%!error gsum () +%!error gsum (1, 2, 3) +*/ + +// PKG_ADD: autoload ("gsumsq", "gf.oct"); +// PKG_DEL: autoload ("gsumsq", "gf.oct", "remove"); +DEFUN_DLD (gsumsq, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} gsumsq (@var{x}, @var{dim})\n\ +Sum of squares of elements along dimension @var{dim} of Galois array.\n\ +If @var{dim} is omitted, it defaults to 1 (column-wise sum of squares).\n\ +\n\ +This function is equivalent to computing\n\ +@example\n\ +gsum (x .* conj (x), dim)\n\ +@end example\n\ +but it uses less memory.\n\ +@seealso{sumsq}\n\ +@end deftypefn") +{ + DATA_REDUCTION (sumsq); +} + +/* +%% Test input validation +%!error gsumsq () +%!error gsumsq (1, 2, 3) +*/ + +// PKG_ADD: autoload ("gsqrt", "gf.oct"); +// PKG_DEL: autoload ("gsqrt", "gf.oct", "remove"); +DEFUN_DLD (gsqrt, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} gsqrt (@var{x})\n\ +Compute the square root of @var{x}, element by element, in a Galois Field.\n\ +@seealso{exp}\n\ +@end deftypefn") +{ + octave_value retval; + int nargin = args.length (); + + if (nargin != 1) + { + print_usage (); + return retval; + } + + if (!galois_type_loaded || (args(0).type_id () != + octave_galois::static_type_id ())) + { + OCTAVE__ERR_WRONG_TYPE_ARG ("gsqrt", args(0)); + return retval; + } + + galois a = ((const octave_galois&) args(0).get_rep ()).galois_value (); + + retval = new octave_galois (a.sqrt ()); + + return retval; +} + +/* +%% Test input validation +%!error gsqrt () +%!error gsqrt (1, 2) +*/ + +// PKG_ADD: autoload ("glog", "gf.oct"); +// PKG_DEL: autoload ("glog", "gf.oct", "remove"); +DEFUN_DLD (glog, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} glog (@var{x})\n\ +Compute the natural logarithm for each element of @var{x} for a Galois\n\ +array.\n\ +@seealso{log}\n\ +@end deftypefn") +{ + octave_value retval; + int nargin = args.length (); + + if (nargin != 1) + { + print_usage (); + return retval; + } + + if (!galois_type_loaded || (args(0).type_id () != + octave_galois::static_type_id ())) + { + OCTAVE__ERR_WRONG_TYPE_ARG ("glog", args(0)); + return retval; + } + + galois a = ((const octave_galois&) args(0).get_rep ()).galois_value (); + + retval = new octave_galois (a.log ()); + + return retval; +} + +/* +%% Test input validation +%!error glog () +%!error glog (1, 2) +*/ + +// PKG_ADD: autoload ("gexp", "gf.oct"); +// PKG_DEL: autoload ("gexp", "gf.oct", "remove"); +DEFUN_DLD (gexp, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} gexp (@var{x})\n\ +Compute the anti-logarithm for each element of @var{x} for a Galois\n\ +array.\n\ +@seealso{exp}\n\ +@end deftypefn") +{ + octave_value retval; + int nargin = args.length (); + + if (nargin != 1) + { + print_usage (); + return retval; + } + + if (!galois_type_loaded || (args(0).type_id () != + octave_galois::static_type_id ())) + { + OCTAVE__ERR_WRONG_TYPE_ARG ("gexp", args(0)); + return retval; + } + + galois a = ((const octave_galois&) args(0).get_rep ()).galois_value (); + + retval = new octave_galois (a.exp ()); + + return retval; +} + +/* +%% Test input validation +%!error gexp () +%!error gexp (1, 2) +*/ + +static inline int +modn (int x, int m, int n) +{ + while (x >= n) + { + x -= n; + x = (x >> m) + (x & n); + } + return x; +} + +galois +filter (galois& b, galois& a, galois& x, galois& si) +{ + int ab_len = (a.numel () > b.numel () ? a.numel () : b.numel ()); + b.resize (dim_vector (ab_len, 1), 0); + galois retval (x.numel (), 1, 0, b.m (), b.primpoly ()); + int norm = a(0, 0); + + if (norm == 0) + { + error ("gfilter: the first element of a must be non-zero"); + return galois (); + } + if (si.numel () != ab_len - 1) + { + error ("gfilter: si must be a vector of length max(length(a), length(b)) - 1"); + return galois (); + } + if (norm != 1) + { + int idx_norm = b.index_of (norm); + for (int i = 0; i < b.numel (); i++) + { + if (b(i, 0) != 0) + b(i, 0) = b.alpha_to (modn (b.index_of (b(i, 0))-idx_norm+b.n (), + b.m (), b.n ())); + } + } + if (a.numel () > 1) + { + a.resize (dim_vector (ab_len, 1), 0); + + if (norm != 1) + { + int idx_norm = a.index_of (norm); + for (int i = 0; i < a.numel (); i++) + if (a(i, 0) != 0) + a(i, 0) = a.alpha_to (modn (a.index_of (a(i, 0))-idx_norm+a.n (), + a.m (), a.n ())); + } + + for (int i = 0; i < x.numel (); i++) + { + retval(i, 0) = si(0, 0); + if ((b(0, 0) != 0) && (x(i, 0) != 0)) + retval(i, 0) ^= b.alpha_to (modn (b.index_of (b(0, 0)) + + b.index_of (x(i, 0)), b.m (), b.n ())); + if (si.numel () > 1) + { + for (int j = 0; j < si.numel () - 1; j++) + { + si(j, 0) = si(j+1, 0); + if ((a(j+1, 0) != 0) && (retval(i, 0) != 0)) + si(j, 0) ^= a.alpha_to (modn (a.index_of (a(j+1, 0)) + + a.index_of (retval(i, 0)), a.m (), a.n ())); + if ((b(j+1, 0) != 0) && (x(i, 0) != 0)) + si(j, 0) ^= b.alpha_to (modn (b.index_of (b(j+1, 0)) + + b.index_of (x(i, 0)), b.m (), b.n ())); + } + si(si.numel ()-1, 0) = 0; + if ((a(si.numel (), 0) != 0) && (retval(i, 0) != 0)) + si(si.numel ()-1, 0) ^= a.alpha_to (modn (a.index_of (a(si.numel (), 0)) + + a.index_of (retval(i, 0)), + a.m (), a.n ())); + + if ((b(si.numel (), 0) != 0) && (x(i, 0) != 0)) + si(si.numel ()-1, 0) ^= b.alpha_to (modn (b.index_of (b(si.numel (), 0)) + + b.index_of (x(i, 0)), + b.m (), b.n ())); + } + else + { + si(0, 0) = 0; + if ((a(1, 0) != 0) && (retval(i, 0) != 0)) + si(0, 0) ^= a.alpha_to (modn (a.index_of (a(1, 0))+ + a.index_of (retval(i, 0)), a.m (), a.n ())); + if ((b(1, 0) != 0) && (x(i, 0) != 0)) + si(0, 0) ^= b.alpha_to (modn (b.index_of (b(1, 0))+ + b.index_of (x(i, 0)), b.m (), b.n ())); + } + } + } + else if (si.numel () > 0) + { + for (int i = 0; i < x.numel (); i++) + { + retval(i, 0) = si(0, 0); + if ((b(0, 0) != 0) && (x(i, 0) != 0)) + retval(i, 0) ^= b.alpha_to (modn (b.index_of (b(0, 0)) + + b.index_of (x(i, 0)), b.m (), b.n ())); + if (si.numel () > 1) + { + for (int j = 0; j < si.numel () - 1; j++) + { + si(j, 0) = si(j+1, 0); + if ((b(j+1, 0) != 0) && (x(i, 0) != 0)) + si(j, 0) ^= b.alpha_to (modn (b.index_of (b(j+1, 0)) + + b.index_of (x(i, 0)), b.m (), b.n ())); + } + + si(si.numel ()-1, 0) = 0; + if ((b(si.numel (), 0) != 0) && (x(i, 0) != 0)) + si(si.numel ()-1, 0) ^= b.alpha_to (modn (b.index_of (b(si.numel (), 0)) + + b.index_of (x(i, 0)), + b.m (), b.n ())); + } + else + { + si(0, 0) = 0; + if ((b(1, 0) != 0) && (x(i, 0) != 0)) + si(0, 0) ^= b.alpha_to (modn (b.index_of (b(1, 0)) + + b.index_of (x(i, 0)), b.m (), b.n ())); + } + } + } + else + for (int i = 0; i < x.numel (); i++) + if ((b(0, 0) != 0) && (x(i, 0) != 0)) + retval(i, 0) = b.alpha_to (modn (b.index_of (b(0, 0)) + + b.index_of (x(i, 0)), b.m (), b.n ())); + + return retval; +} + + +// PKG_ADD: autoload ("gfilter", "gf.oct"); +// PKG_DEL: autoload ("gfilter", "gf.oct", "remove"); +DEFUN_DLD (gfilter, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {y =} gfilter (@var{b}, @var{a}, @var{x})\n\ +@deftypefnx {Loadable Function} {[@var{y}, @var{sf}] =} gfilter (@var{b}, @var{a}, @var{x}, @var{si})\n\ +Digital filtering of vectors in a Galois Field. Returns the solution to\n\ +the following linear, time-invariant difference equation over a Galois\n\ +Field:\n\ +@tex\n\ +$$\n\ +\\sum_{k=0}^N a_{k+1} y_{n-k} = \\sum_{k=0}^M b_{k+1} x_{n-k}, \\qquad\n\ + 1 \\le n \\le P\n\ +$$\n\ +@end tex\n\ +@ifnottex\n\ +\n\ +@smallexample\n\ +@group\n\ + N M\n\ + SUM a(k+1) y(n-k) = SUM b(k+1) x(n-k) for 1<=n<=length(x)\n\ + k=0 k=0\n\ +@end group\n\ +@end smallexample\n\ +@end ifnottex\n\ +\n\ +@noindent\n\ +where\n\ +@tex\n\ + $a \\in \\Re^{N-1}$, $b \\in \\Re^{M-1}$, and $x \\in \\Re^P$.\n\ +@end tex\n\ +@ifnottex\n\ + N=length(a)-1 and M=length(b)-1.\n\ +@end ifnottex\n\ +An equivalent form of this equation is:\n\ +@tex\n\ +$$\n\ +y_n = -\\sum_{k=1}^N c_{k+1} y_{n-k} + \\sum_{k=0}^M d_{k+1} x_{n-k}, \\qquad\n\ + 1 \\le n \\le P\n\ +$$\n\ +@end tex\n\ +@ifnottex\n\ +\n\ +@smallexample\n\ +@group\n\ + N M\n\ + y(n) = - SUM c(k+1) y(n-k) + SUM d(k+1) x(n-k) for 1<=n<=length(x)\n\ + k=1 k=0\n\ +@end group\n\ +@end smallexample\n\ +@end ifnottex\n\ +\n\ +@noindent\n\ +where\n\ +@tex\n\ +$c = a/a_1$ and $d = b/a_1$.\n\ +@end tex\n\ +@ifnottex\n\ + c = a/a(1) and d = b/a(1).\n\ +@end ifnottex\n\ +\n\ +If the fourth argument @var{si} is provided, it is taken as the initial\n\ +state of the system and the final state is returned as @var{sf}. The\n\ +state vector is a column vector whose length is equal to the length of\n\ +the longest coefficient vector minus one. If @var{si} is not supplied,\n\ +the initial state vector is set to all zeros.\n\ +@seealso{filter}\n\ +@end deftypefn") +{ + octave_value_list retval; + + int nargin = args.length (); + + if (nargin < 3 || nargin > 4) + { + print_usage (); + return retval; + } + + if (!galois_type_loaded) + { + error ("gfilter: wrong argument types"); + return retval; + } + + bool x_is_row_vector = (args(2).rows () == 1); + bool si_is_row_vector = (nargin == 4 && args(3).rows () == 1); + galois b, a, x, si; + bool ib=false, ia=false, ix = false, isi=false; + + if (args(0).type_id () == octave_galois::static_type_id ()) + { + b = ((const octave_galois&) args(0).get_rep ()).galois_value (); + ib = true; + } + if (args(1).type_id () == octave_galois::static_type_id ()) + { + a = ((const octave_galois&) args(1).get_rep ()).galois_value (); + ia = true; + } + if (args(2).type_id () == octave_galois::static_type_id ()) + { + x = ((const octave_galois&) args(2).get_rep ()).galois_value (); + ix = true; + } + if (nargin == 4) + { + if (args(3).type_id () == octave_galois::static_type_id ()) + { + si = ((const octave_galois&) args(3).get_rep ()).galois_value (); + isi = true; + } + } + + if (!ib && !ia && !ix && !isi) + { + error ("gfilter: wrong argument types"); + return retval; + } + + if (!ib) + { + if (ia) + b = galois (args(0).matrix_value (), a.m (), a.primpoly ()); + else if (ix) + b = galois (args(0).matrix_value (), x.m (), x.primpoly ()); + else if (isi) + b = galois (args(0).matrix_value (), si.m (), si.primpoly ()); + } + if (!ia) + a = galois (args(1).matrix_value (), b.m (), b.primpoly ()); + if (!ix) + x = galois (args(2).matrix_value (), b.m (), b.primpoly ()); + + if (nargin == 4) + { + if (!isi) + si = galois (args(3).matrix_value (), b.m (), b.primpoly ()); + } + else + { + int a_len = a.numel (); + int b_len = b.numel (); + + int si_len = (a_len > b_len ? a_len : b_len) - 1; + + si = galois (si_len, 1, 0, b.m (), b.primpoly ()); + } + + if ((b.m () != a.m ()) || (b.m () != x.m ()) || (b.m () != si.m ()) || + (b.primpoly () != a.primpoly ()) || (b.primpoly () != x.primpoly ()) || + (b.primpoly () != si.primpoly ())) + { + error ("gfilter: arguments must be in same galois field"); + return retval; + } + + if (b.cols () > 1) + b = b.transpose (); + if (a.cols () > 1) + a = a.transpose (); + if (x.cols () > 1) + x = x.transpose (); + if (si.cols () > 1) + si = si.transpose (); + + if (b.cols () > 1 || a.cols () > 1 || x.cols () > 1 || si.cols () > 1) + { + error ("gfilter: arguments must be vectors"); + return retval; + } + + galois y (filter (b, a, x, si)); + if (nargout == 2) + { + if (si_is_row_vector) + retval(1) = new octave_galois (si.transpose ()); + else + retval(1) = new octave_galois (si); + } + + if (x_is_row_vector) + retval(0) = new octave_galois (y.transpose ()); + else + retval(0) = new octave_galois (y); + + return retval; +} + +/* +%% Test input validation +%!error gfilter () +%!error gfilter (1) +%!error gfilter (1, 2) +%!error gfilter (1, 2, 3, 4, 5) +*/ + +// PKG_ADD: autoload ("glu", "gf.oct"); +// PKG_DEL: autoload ("glu", "gf.oct", "remove"); +DEFUN_DLD (glu, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {[@var{l}, @var{u}, @var{p}] =} glu (@var{a})\n\ +@cindex LU decomposition of Galois matrix\n\ +Compute the LU decomposition of @var{a} in a Galois Field. The result is\n\ +returned in a permuted form, according to the optional return value\n\ +@var{p}. For example, given the matrix\n\ +@code{a = gf ([1, 2; 3, 4], 3)},\n\ +\n\ +@example\n\ +[l, u, p] = glu (a)\n\ +@end example\n\ +\n\ +@noindent\n\ +returns\n\ +\n\ +@example\n\ +l =\n\ +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11)\n\ +\n\ +Array elements =\n\ +\n\ + 1 0\n\ + 6 1\n\ +\n\ +u =\n\ +GF(2^3) array. Primitive Polynomial = D^3+D+1 (decimal 11)\n\ +\n\ +Array elements =\n\ +\n\ + 3 4\n\ + 0 7\n\ +\n\ +p =\n\ +\n\ +Permutation Matrix\n\ +\n\ + 0 1\n\ + 1 0\n\ +\n\ +@end example\n\ +\n\ +Such that @code{@var{p} * @var{a} = @var{l} * @var{u}}. If the argument\n\ +@var{p} is not included then the permutations are applied to @var{l}\n\ +so that @code{@var{a} = @var{l} * @var{u}}. @var{l} is then a pseudo-\n\ +lower triangular matrix. The matrix @var{a} can be rectangular.\n\ +@seealso{lu}\n\ +@end deftypefn") +{ + octave_value_list retval; + + + int nargin = args.length (); + + if (nargin != 1 || nargout > 3) + { + print_usage (); + return retval; + } + + octave_value arg = args(0); + + if (!galois_type_loaded || (arg.type_id () != + octave_galois::static_type_id ())) + { + OCTAVE__ERR_WRONG_TYPE_ARG ("glu", arg); + return retval; + } + + galois m = ((const octave_galois&) arg.get_rep ()).galois_value (); + + int nr = arg.rows (); + int nc = arg.columns (); + + int arg_is_empty = arg.OV_ISEMPTY(); + + if (arg_is_empty < 0) + return retval; + else if (arg_is_empty > 0) + { + retval(0) = new octave_galois (galois (0, 0, 0, m.m (), m.primpoly ())); + retval(1) = new octave_galois (galois (0, 0, 0, m.m (), m.primpoly ())); + retval(2) = new octave_galois (galois (0, 0, 0, m.m (), m.primpoly ())); + return retval; + } + + if (! error_state) + { + galoisLU fact (m); + + switch (nargout) + { + case 0: + case 1: + case 2: + { + // While we don't have sparse galois matrices converting the + // permutation matrix to a full matrix is the best we can do. + Matrix P = Matrix (fact.P ()); + galois L = P.transpose () * fact.L (); + retval(1) = new octave_galois (fact.U ()); + retval(0) = new octave_galois (L); + } + break; + + case 3: + default: + retval(2) = fact.P (); + retval(1) = new octave_galois (fact.U ()); + retval(0) = new octave_galois (fact.L ()); + break; + } + } + + return retval; +} + +/* +%% Test input validation +%!error glu () +%!error glu (1, 2) +*/ + +// PKG_ADD: autoload ("ginv", "gf.oct"); +// PKG_DEL: autoload ("ginv", "gf.oct", "remove"); +DEFUN_DLD (ginv, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {[@var{x}, @var{rcond}] =} ginv (@var{a})\n\ +Compute the inverse of the square matrix @var{a}. Return an estimate\n\ +of the reciprocal condition number if requested, otherwise warn of an\n\ +ill-conditioned matrix if the reciprocal condition number is small.\n\ +@seealso{inv}\n\ +@end deftypefn") +{ + octave_value_list retval; + + int nargin = args.length (); + + if (nargin != 1) + { + print_usage (); + return retval; + } + + octave_value arg = args(0); + + int nr = arg.rows (); + int nc = arg.columns (); + + if (!galois_type_loaded || (arg.type_id () != + octave_galois::static_type_id ())) + { + OCTAVE__ERR_WRONG_TYPE_ARG ("ginverse", arg); + return retval; + } + + galois m = ((const octave_galois&) arg.get_rep ()).galois_value (); + + int arg_is_empty = arg.OV_ISEMPTY (); + + if (arg_is_empty < 0) + return retval; + else if (arg_is_empty > 0) + { + retval(0) = new octave_galois (galois (0, 0, 0, m.m (), m.primpoly ())); + return retval; + } + if (nr != nc) + { + OCTAVE__ERR_SQUARE_MATRIX_REQUIRED ("ginverse"); + return retval; + } + + if (! error_state) + { + int info; + double rcond = 0.0; + + galois result = m.inverse (info, 1); + + if (nargout > 1) + retval(1) = rcond; + + retval(0) = new octave_galois (result); + + if (nargout < 2 && info == -1) + warning ("inverse: matrix singular to machine precision, rcond = %g", rcond); + } + + return retval; +} + +/* +%% Test input validation +%!error ginv () +%!error ginv (1, 2) +*/ + +// FIXME: this should really be done with an alias, but +// alias_builtin() won't do the right thing if we are actually using +// dynamic linking. + +// PKG_ADD: autoload ("ginverse", "gf.oct"); +// PKG_DEL: autoload ("ginverse", "gf.oct", "remove"); +DEFUN_DLD (ginverse, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {} ginverse (@var{a})\n\ +Compute the inverse of the square matrix @var{a}. Return an estimate\n\ +of the reciprocal condition number if requested, otherwise warn of an\n\ +ill-conditioned matrix if the reciprocal condition number is small.\n\ +@seealso{ginv}\n\ +@end deftypefn") +{ + return Fginv (args, nargout); +} + +/* +%% Test input validation +%!error ginverse () +%!error ginverse (1, 2) +*/ + +// PKG_ADD: autoload ("gdet", "gf.oct"); +// PKG_DEL: autoload ("gdet", "gf.oct", "remove"); +DEFUN_DLD (gdet, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{d} =} gdet (@var{a})\n\ +Compute the determinant of the Galois array @var{a}.\n\ +@seealso{det}\n\ +@end deftypefn") +{ + octave_value retval; + + int nargin = args.length (); + + if (nargin != 1) + { + print_usage (); + return retval; + } + + octave_value arg = args(0); + + if (!galois_type_loaded || (arg.type_id () != + octave_galois::static_type_id ())) + { + OCTAVE__ERR_WRONG_TYPE_ARG ("gdet", arg); + return retval; + } + + int nr = arg.rows (); + int nc = arg.columns (); + + galois m = ((const octave_galois&) arg.get_rep ()).galois_value (); + + int arg_is_empty = arg.OV_ISEMPTY (); + + if (arg_is_empty < 0) + return retval; + else if (arg_is_empty > 0) + { + retval = new octave_galois (galois (1, 1, 1, m.m (), m.primpoly ())); + return retval; + } + + if (nr != nc) + { + OCTAVE__ERR_SQUARE_MATRIX_REQUIRED ("det"); + return retval; + } + + retval = new octave_galois (m.determinant ()); + return retval; +} + +/* +%% Test input validation +%!error gdet () +%!error gdet (1, 2) +*/ + +// PKG_ADD: autoload ("grank", "gf.oct"); +// PKG_DEL: autoload ("grank", "gf.oct", "remove"); +DEFUN_DLD (grank, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{d} =} grank (@var{a})\n\ +Compute the rank of the Galois array @var{a} by counting the independent\n\ +rows and columns.\n\ +@seealso{rank}\n\ +@end deftypefn") +{ + octave_value retval; + + int nargin = args.length (); + + if (nargin != 1) + { + print_usage (); + return retval; + } + + octave_value arg = args(0); + + if (!galois_type_loaded || (arg.type_id () != + octave_galois::static_type_id ())) + { + OCTAVE__ERR_WRONG_TYPE_ARG ("grank", arg); + return retval; + } + + int nr = arg.rows (); + int nc = arg.columns (); + + galois m = ((const octave_galois&) arg.get_rep ()).galois_value (); + + int arg_is_empty = arg.OV_ISEMPTY (); + + if (arg_is_empty > 0) + retval = 0.0; + else if (arg_is_empty == 0) + { + int d = 0; + int mm = m.m (); + int mn = m.n (); + OCTAVE_LOCAL_BUFFER (int, ci, nr); + + for (int i = 0; i < nc; i++) + { + int idx = -1; + int iel = 0; + for (int j = 0; j < nr; j++) + { + ci[j] = m.elem (j, i); + if (ci[j] != 0 && idx == -1) + { + iel = ci[j]; + idx = j; + } + } + + if (idx != -1) + { + d++; + int indx = m.index_of (iel); + for (int j = 0; j < nr; j++) + if (ci[j] != 0) + ci[j] = m.alpha_to (modn (m.index_of (ci[j]) - indx + mn, mm, mn)); + + for (int j = i+1; j < nc; j++) + { + if (m.elem (idx, j) != 0) + { + indx = m.index_of (m.elem (idx, j)); + for (int k = 0; k < nr; k++) + if (ci[k] != 0) + m.elem (k, j) ^= m.alpha_to (modn (m.index_of (ci[k]) + indx + + mn, mm, mn)); + } + } + } + } + retval = (double)d; + } + return retval; +} + +/* +%% Test input validation +%!error grank () +%!error grank (1, 2) +*/ + +// PKG_ADD: autoload ("rsenc", "gf.oct"); +// PKG_DEL: autoload ("rsenc", "gf.oct", "remove"); +DEFUN_DLD (rsenc, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{code} =} rsenc (@var{msg}, @var{n}, @var{k})\n\ +@deftypefnx {Loadable Function} {@var{code} =} rsenc (@var{msg}, @var{n}, @var{k}, @var{g})\n\ +@deftypefnx {Loadable Function} {@var{code} =} rsenc (@var{msg}, @var{n}, @var{k}, @var{fcr}, @var{prim})\n\ +@deftypefnx {Loadable Function} {@var{code} =} rsenc (@dots{}, @var{parpos})\n\ +Encodes the message @var{msg} using a [@var{n},@var{k}] Reed-Solomon coding.\n\ +The variable @var{msg} is a Galois array with @var{k} columns and an arbitrary\n\ +number of rows. Each row of @var{msg} represents a single block to be coded\n\ +by the Reed-Solomon coder. The coded message is returned in the Galois\n\ +array @var{code} containing @var{n} columns and the same number of rows as\n\ +@var{msg}.\n\ +\n\ +The use of @code{rsenc} can be seen in the following short example.\n\ +\n\ +@example\n\ +m = 3; n = 2^m -1; k = 3;\n\ +msg = gf ([1 2 3; 4 5 6], m);\n\ +code = rsenc (msg, n, k);\n\ +@end example\n\ +\n\ +If @var{n} does not equal @code{2^@var{m}-1}, where m is an integer, then a\n\ +shorten Reed-Solomon coding is used where zeros are added to the start of\n\ +each row to obtain an allowable codeword length. The returned @var{code}\n\ +has these prepending zeros stripped.\n\ +\n\ +By default the generator polynomial used in the Reed-Solomon coding is based\n\ +on the properties of the Galois Field in which @var{msg} is given. This\n\ +default generator polynomial can be overridden by a polynomial in @var{g}.\n\ +Suitable generator polynomials can be constructed with @code{rsgenpoly}.\n\ +@var{fcr} is an integer value, and it is taken to be the first consecutive\n\ +root of the generator polynomial. The variable @var{prim} is then the\n\ +primitive element used to construct the generator polynomial, such that\n\ +@tex\n\ +$g = (x - A^b) (x - A^{b+p}) \\cdots (x - A ^{b+2tp-1})$.\n\ +@end tex\n\ +@ifnottex\n\ +\n\ +@var{g} = (@var{x} - A^@var{b}) * (@var{x} - A^(@var{b}+@var{prim})) * ... * (@var{x} - A^(@var{b}+2*@var{t}*@var{prim}-1)).\n\ +@end ifnottex\n\ +\n\ +where @var{b} is equal to @code{@var{fcr} * @var{prim}}. By default @var{fcr}\n\ +and @var{prim} are both 1.\n\ +\n\ +By default the parity symbols are placed at the end of the coded message.\n\ +The variable @var{parpos} controls this positioning and can take the values\n\ +@code{\"beginning\"} or @code{\"end\"}.\n\ +@seealso{gf, rsdec, rsgenpoly}\n\ +@end deftypefn") +{ + octave_value retval; + int nargin = args.length (); + + if (nargin < 3 || nargin > 5) + { + print_usage (); + return retval; + } + + if (!galois_type_loaded || (args(0).type_id () != + octave_galois::static_type_id ())) + { + OCTAVE__ERR_WRONG_TYPE_ARG ("rsenc", args(0)); + return retval; + } + + galois msg = ((const octave_galois&) args(0).get_rep ()).galois_value (); + int nsym = msg.rows (); + int primpoly = msg.primpoly (); + int n = args(1).nint_value (); + int k = args(2).nint_value (); + + int m = 1; + while (n > (1< __OCTAVE_GALOIS_MAX_M)) + { + error ("rsenc: invalid values of message and codeword length"); + return retval; + } + + if ((n-k) & 1) + { + error ("rsenc: difference of message and codeword length must be even"); + return retval; + } + + int nroots = n-k; + galois genpoly; + bool have_genpoly = false; + bool parity_at_end = true; + int fcr = 0; + int prim = 0; + + for (int i = 3; i < nargin; i++) + { + if (args(i).is_string ()) + { + std::string parstr = args(i).string_value (); + for (int j = 0; j < (int)parstr.length (); j++) + parstr[j] = toupper (parstr[j]); + + if (!parstr.compare("END")) + { + parity_at_end = true; + } + else if (!parstr.compare("BEGINNING")) + { + parity_at_end = false; + } + else + { + error ("rsenc: unrecoginized parity position"); + return retval; + } + } + else + { + if (args(i).type_id () == octave_galois::static_type_id ()) + { + if (have_genpoly) + { + print_usage (); + return retval; + } + genpoly = ((const octave_galois&) args(i).get_rep ()).galois_value (); + + if (genpoly.cols () > genpoly.rows ()) + genpoly = genpoly.transpose (); + } + else + { + if (have_genpoly) + { + if (prim != 0) + { + print_usage (); + return retval; + } + prim = args(i).nint_value (); + } + else + fcr = args(i).nint_value (); + } + have_genpoly = true; + } + } + + if ((genpoly.rows () == 0) || (genpoly.cols () == 0)) + { + if (fcr == 0) + fcr = 1; + if (prim == 0) + prim = 1; + + // Create polynomial of right length. + genpoly = galois (nroots+1, 1, 0, m, primpoly); + + genpoly(nroots, 0) = 1; + int i, root; + for (i = 0, root=fcr*prim; i < nroots; i++, root += prim) + { + genpoly(nroots-i-1, 0) = 1; + + // Multiply genpoly by @**(root + x) + for (int j = i; j > 0; j--) + { + int k = nroots - j; + if (genpoly(k, 0) != 0) + genpoly(k, 0) = genpoly(k+1, 0) + ^ genpoly.alpha_to (modn (genpoly.index_of (genpoly(k, 0)) + + root, m, n)); + else + genpoly(k, 0) = genpoly(k+1, 0); + } + // genpoly(nroots,0) can never be zero + genpoly(nroots, 0) = genpoly.alpha_to (modn (genpoly.index_of (genpoly(nroots, 0)) + + root, m, n)); + } + + } + else + { + if (genpoly.cols () != 1) + { + error ("rsenc: the generator polynomial must be a vector"); + return retval; + } + + if (genpoly.primpoly () != primpoly) + { + error ("rsenc: the generator polynomial must be same galois field " + "as the message"); + return retval; + } + + if (genpoly.rows () != nroots+1) + { + error ("rsenc: generator polynomial has incorrect order"); + return retval; + } + } + + int norm = genpoly(0, 0); + + // Take logarithm of generator polynomial, for faster coding + for (int i = 0; i < nroots+1; i++) + genpoly(i, 0) = genpoly.index_of (genpoly(i, 0)); + + // Add space for parity block + msg.resize (dim_vector (nsym, n), 0); + + // The code below basically finds the parity bits by treating the + // message as a polynomial and dividing it by the generator polynomial. + // The parity bits are then the remainder of this division. If the parity + // is at the end the polynomial is treat MSB first, otherwise it is + // treated LSB first + // + // This code could just as easily be written as + // [ignore par] = gdeconv(msg, genpoly); + // But the code below has the advantage of being 20 times faster :-) + + if (parity_at_end) + { + for (int l = 0; l < nsym; l++) + { + galois par (nroots, 1, 0, m, primpoly); + for (int i = 0; i < k; i++) + { + int feedback = par.index_of (par(0, 0) ^ msg(l, i)); + if (feedback != nn) + { + if (norm != 1) + feedback = modn (nn-genpoly(0, 0)+feedback, m, nn); + for (int j = 1; j < nroots; j++) + par(j, 0) ^= par.alpha_to (modn (feedback + + genpoly(j, 0), m, nn)); + } + for (int j = 1; j < nroots; j++) + par(j-1, 0) = par(j, 0); + if (feedback != nn) + par(nroots-1, 0) = par.alpha_to (modn (feedback+ + genpoly(nroots, 0), m, nn)); + else + par(nroots-1, 0) = 0; + } + for (int j = 0; j < nroots; j++) + msg(l, k+j) = par(j, 0); + } + } + else + { + for (int l = 0; l < nsym; l++) + { + for (int i=k; i > 0; i--) + msg(l, i+nroots-1) = msg(l, i-1); + for (int i = 0; i nroots; i--) + { + int feedback = par.index_of (par(0, 0) ^ msg(l, i-1)); + if (feedback != nn) + { + if (norm != 1) + feedback = modn (nn-genpoly(0, 0)+feedback, m, nn); + for (int j = 1; j < nroots; j++) + par(j, 0) ^= par.alpha_to (modn (feedback + + genpoly(j, 0), m, nn)); + } + for (int j = 1; j < nroots; j++) + par(j-1, 0) = par(j, 0); + if (feedback != nn) + par(nroots-1, 0) = par.alpha_to (modn (feedback+ + genpoly(nroots, 0), m, nn)); + else + par(nroots-1, 0) = 0; + } + for (int j = 0; j < nroots; j++) + msg(l, j) = par(nroots-j-1, 0); + } + } + + retval = new octave_galois (msg); + + return retval; +} + +/* +%% Test input validation +%!error rsenc () +%!error rsenc (1) +%!error rsenc (1, 2) +%!error rsenc (1, 2, 3, 4, 5, 6) +*/ + +int +decode_rs(galois& data, const int prim, const int iprim, const int nroots, + const int fcr, const int drow, const bool msb_first) +{ + int deg_lambda, el, deg_omega; + int i, j, r, k; + int q, tmp, num1, num2, den, discr_r; + int syn_error, count; + int m = data.m (); + int n = data.n (); + int A0 = n; + + /* Err Locator and syndrome poly */ + OCTAVE_LOCAL_BUFFER (int, lambda, nroots+1); + OCTAVE_LOCAL_BUFFER (int, s, nroots); + + OCTAVE_LOCAL_BUFFER (int, b, nroots+1); + OCTAVE_LOCAL_BUFFER (int, t, nroots+1); + OCTAVE_LOCAL_BUFFER (int, omega, nroots+1); + + OCTAVE_LOCAL_BUFFER (int, root, nroots); + OCTAVE_LOCAL_BUFFER (int, reg, nroots+1); + OCTAVE_LOCAL_BUFFER (int, loc, nroots); + + /* form the syndromes; i.e., evaluate data(x) at roots of g(x) */ + if (msb_first) + { + for (i = 0; i < nroots; i++) + s[i] = data(drow, 0); + + for (j = 1; j < n; j++) + for (i = 0; i0; j--) + for (i = 0; i < nroots; i++) + if(s[i] == 0) + s[i] = data(drow, j-1); + else + s[i] = data(drow, j-1) ^ data.alpha_to (modn (data.index_of (s[i]) + + (fcr+i)*prim, m, n)); + } + + /* Convert syndromes to index form, checking for nonzero condition */ + syn_error = 0; + for (i = 0; i < nroots; i++) + { + syn_error |= s[i]; + s[i] = data.index_of (s[i]); + } + + if (!syn_error) + /* if syndrome is zero, data(drow,:) is a codeword and there are no + * errors to correct. So return data(drow,:) unmodified + */ + return 0; + + memset(&lambda[1], 0, nroots*sizeof (lambda[0])); + lambda[0] = 1; + + for (i = 0; i < nroots+1; i++) + b[i] = data.index_of (lambda[i]); + + /* + * Begin Berlekamp-Massey algorithm to determine error locator polynomial + */ + r = 0; + el = 0; + while (++r <= nroots) + {/* r is the step number */ + /* Compute discrepancy at the r-th step in poly-form */ + discr_r = 0; + for (i = 0; i < r; i++) + { + if ((lambda[i] != 0) && (s[r-i-1] != A0)) + { + discr_r ^= data.alpha_to (modn (data.index_of (lambda[i]) + + s[r-i-1], m, n)); + } + } + discr_r = data.index_of (discr_r); /* Index form */ + if (discr_r == A0) + { + /* 2 lines below: B(x) <-- x*B(x) */ + memmove(&b[1], b, nroots*sizeof (b[0])); + b[0] = A0; + } + else + { + /* 7 lines below: T(x) <-- lambda(x) - discr_r*x*b(x) */ + t[0] = lambda[0]; + for (i = 0 ; i < nroots; i++) + { + if(b[i] != A0) + t[i+1] = lambda[i+1] ^ data.alpha_to (modn (discr_r + b[i], m, n)); + else + t[i+1] = lambda[i+1]; + } + if (2 * el <= r - 1) + { + el = r - el; + /* + * 2 lines below: B(x) <-- inv(discr_r) * + * lambda(x) + */ + for (i = 0; i <= nroots; i++) + b[i] = (lambda[i] == 0) ? A0 : modn (data.index_of (lambda[i]) - + discr_r + n, m, n); + } + else + { + /* 2 lines below: B(x) <-- x*B(x) */ + memmove(&b[1], b, nroots*sizeof (b[0])); + b[0] = A0; + } + memcpy(lambda, t, (nroots+1)*sizeof (t[0])); + } + } + + /* Convert lambda to index form and compute deg(lambda(x)) */ + deg_lambda = 0; + for (i = 0; i < nroots+1; i++) + { + lambda[i] = data.index_of (lambda[i]); + if(lambda[i] != A0) + deg_lambda = i; + } + + /* Find roots of the error locator polynomial by Chien search */ + memcpy(®[1], &lambda[1], nroots*sizeof (reg[0])); + count = 0; /* Number of roots of lambda(x) */ + for (i = 1, k = iprim-1; i <= n; i++, k = modn (k+iprim, m, n)) + { + q = 1; /* lambda[0] is always 0 */ + for (j = deg_lambda; j > 0; j--) + { + if (reg[j] != A0) + { + reg[j] = modn (reg[j] + j, m, n); + q ^= data.alpha_to (reg[j]); + } + } + if (q != 0) + continue; /* Not a root */ + /* store root (index-form) and error location number */ + root[count] = i; + loc[count] = k; + /* If we've already found max possible roots, + * abort the search to save time + */ + if(++count == deg_lambda) + break; + } + if (deg_lambda != count) + { + /* + * deg(lambda) unequal to number of roots => uncorrectable + * error detected + */ + return -1; + } + /* + * Compute err evaluator poly omega(x) = s(x)*lambda(x) (modulo + * x**nroots). in index form. Also find deg(omega). + */ + deg_omega = 0; + for (i = 0; i < nroots; i++) + { + tmp = 0; + j = (deg_lambda < i) ? deg_lambda : i; + for (; j >= 0; j--) + { + if ((s[i - j] != A0) && (lambda[j] != A0)) + tmp ^= data.alpha_to (modn (s[i - j] + lambda[j], m, n)); + } + if(tmp != 0) + deg_omega = i; + omega[i] = data.index_of (tmp); + } + omega[nroots] = A0; + + /* + * Compute error values in poly-form. num1 = omega(inv(X(l))), num2 = + * inv(X(l))**(fcr-1) and den = lambda_pr(inv(X(l))) all in poly-form + */ + for (j = count-1; j >= 0; j--) + { + num1 = 0; + for (i = deg_omega; i >= 0; i--) + { + if (omega[i] != A0) + num1 ^= data.alpha_to (modn (omega[i] + i * root[j], m, n)); + } + num2 = data.alpha_to (modn (root[j] * (fcr - 1) + n, m, n)); + den = 0; + + /* lambda[i+1] for i even is the formal deriv lambda_pr of lambda[i] */ + for (i = (deg_lambda < nroots-1 ? deg_lambda : nroots-1) & ~1; i >= 0; + i -=2) + { + if(lambda[i+1] != A0) + den ^= data.alpha_to (modn (lambda[i+1] + i * root[j], m, n)); + } + if (den == 0) + { + count = -1; + break; + } + /* Apply error to data */ + if (num1 != 0) + { + if (msb_first) + data(drow, loc[j]) ^= data.alpha_to (modn (data.index_of (num1) + + data.index_of (num2) + + n - data.index_of (den), + m, n)); + else + data(drow, n-loc[j]-1) ^= data.alpha_to (modn (data.index_of (num1) + + data.index_of (num2) + + n - data.index_of (den), + m, n)); + } + } + + return count; +} + +// PKG_ADD: autoload ("rsdec", "gf.oct"); +// PKG_DEL: autoload ("rsdec", "gf.oct", "remove"); +DEFUN_DLD (rsdec, args, nargout, + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{msg} =} rsdec (@var{code}, @var{n}, @var{k})\n\ +@deftypefnx {Loadable Function} {@var{msg} =} rsdec (@var{code}, @var{n}, @var{k}, @var{g})\n\ +@deftypefnx {Loadable Function} {@var{msg} =} rsdec (@var{code}, @var{n}, @var{k}, @var{fcr}, @var{prim})\n\ +@deftypefnx {Loadable Function} {@var{msg} =} rsdec (@dots{}, @var{parpos})\n\ +@deftypefnx {Loadable Function} {[@var{msg}, @var{nerr}] =} rsdec (@dots{})\n\ +@deftypefnx {Loadable Function} {[@var{msg}, @var{nerr}, @var{ccode}] =} rsdec (@dots{})\n\ +Decodes the message contained in @var{code} using a [@var{n},@var{k}]\n\ +Reed-Solomon code. The variable @var{code} must be a Galois array with\n\ +@var{n} columns and an arbitrary number of rows. Each row of @var{code}\n\ +represents a single block to be decoded by the Reed-Solomon coder. The\n\ +decoded message is returned in the variable @var{msg} containing @var{k}\n\ +columns and the same number of rows as @var{code}.\n\ +\n\ +If @var{n} does not equal @code{2^@var{m}-1}, where m is an integer, then a\n\ +shorten Reed-Solomon decoding is used where zeros are added to the start of\n\ +each row to obtain an allowable codeword length. The returned @var{msg}\n\ +has these prepending zeros stripped.\n\ +\n\ +By default the generator polynomial used in the Reed-Solomon coding is based\n\ +on the properties of the Galois Field in which @var{msg} is given. This\n\ +default generator polynomial can be overridden by a polynomial in @var{g}.\n\ +Suitable generator polynomials can be constructed with @code{rsgenpoly}.\n\ +@var{fcr} is an integer value, and it is taken to be the first consecutive\n\ +root of the generator polynomial. The variable @var{prim} is then the\n\ +primitive element used to construct the generator polynomial. By default\n\ +@var{fcr} and @var{prim} are both 1. It is significantly faster to specify\n\ +the generator polynomial in terms of @var{fcr} and @var{prim}, since @var{g}\n\ +is converted to this form in any case.\n\ +\n\ +By default the parity symbols are placed at the end of the coded message.\n\ +The variable @var{parpos} controls this positioning and can take the values\n\ +@code{\"beginning\"} or @code{\"end\"}. If the parity symbols are at the end, the message is\n\ +treated with the most-significant symbol first, otherwise the message is\n\ +treated with the least-significant symbol first.\n\ +@seealso{gf, rsenc, rsgenpoly}\n\ +@end deftypefn") +{ + octave_value_list retval; + + int nargin = args.length (); + + if (nargin < 3 || nargin > 5) + { + print_usage (); + return retval; + } + + if (!galois_type_loaded || (args(0).type_id () != + octave_galois::static_type_id ())) + { + OCTAVE__ERR_WRONG_TYPE_ARG ("rsdec", args(0)); + return retval; + } + + galois code = ((const octave_galois&) args(0).get_rep ()).galois_value (); + int nsym = code.rows (); + int primpoly = code.primpoly (); + int n = args(1).nint_value (); + int k = args(2).nint_value (); + + int m = 1; + while (n > (1< __OCTAVE_GALOIS_MAX_M)) + { + error ("rsdec: invalid values of message and codeword length"); + return retval; + } + + if ((n-k) & 1) + { + error ("rsdec: difference of message and codeword length must be even"); + return retval; + } + + int nroots = n-k; + galois genpoly; + bool have_genpoly = false; + bool parity_at_end = true; + int fcr = 0; + int prim = 0; + int iprim; + + for (int i = 3; i < 6; i++) + { + if (nargin > i) + { + if (args(i).is_string ()) + { + std::string parstr = args(i).string_value (); + for (int j = 0; j < (int)parstr.length (); j++) + parstr[j] = toupper (parstr[j]); + + if (!parstr.compare("END")) + { + parity_at_end = true; + } + else if (!parstr.compare("BEGINNING")) + { + parity_at_end = false; + } + else + { + error ("rsdec: unrecoginized parrity position"); + return retval; + } + } + else + { + if (args(i).type_id () == octave_galois::static_type_id ()) + { + if (have_genpoly) + { + print_usage (); + return retval; + } + genpoly = ((const octave_galois&) args(i).get_rep ()).galois_value (); + } + else + { + if (have_genpoly) + { + if (prim != 0) + { + print_usage (); + return retval; + } + prim = args(i).nint_value (); + } + else + fcr = args(i).nint_value (); + } + have_genpoly = true; + } + } + } + + if (have_genpoly) + { + if (fcr != 0) + { + if ((fcr < 1) || (fcr > nn)) + { + error ("rsdec: invalid first consecutive root of generator polynomial"); + return retval; + } + if ((prim < 1) || (prim > nn)) + { + error ("rsdec: invalid primitive element of generator polynomial"); + return retval; + } + } + else + { + if (genpoly.cols () > genpoly.rows ()) + genpoly = genpoly.transpose (); + + if (genpoly.cols () != 1) + { + error ("rsdec: the generator polynomial must be a vector"); + return retval; + } + + if (genpoly.primpoly () != primpoly) + { + error ("rsdec: the generator polynomial must be same galois " + "field as the message"); + return retval; + } + + if (genpoly.rows () != nroots+1) + { + error ("rsdec: generator polynomial has incorrect order"); + return retval; + } + + // Find the roots of the generator polynomial + int count = 0; + OCTAVE_LOCAL_BUFFER (int, roots, nroots); + for (int j = 0; j <= nn; j++) + { + // Evaluate generator polynomial at j + int val = genpoly(0, 0); + int indx = genpoly.index_of (j); + for (int i = 0; i 0; i--) + code(l, i+nn-n-1) = code(l, i-1); + } + + for (int l = 0; l < nsym; l++) + nerr(l) = decode_rs (code, prim, iprim, nroots, fcr, l, parity_at_end); + + if (nn != n) + { + if (parity_at_end) + for (int l = 0; l < nsym; l++) + for (int i = 0; i > n; i--) + code(l, i) = code(l, i+nn-n); + code.resize (dim_vector (nsym, n), 0); + } + + if (parity_at_end) + { + for (int l = 0; l < nsym; l++) + for (int i = 0; i < k; i++) + msg(l, i) = code(l, i); + } + else + { + for (int l = 0; l < nsym; l++) + for (int i = 0; i < k; i++) + msg(l, i) = code(l, nroots+i); + } + + retval(0) = new octave_galois (msg); + retval(1) = octave_value (nerr); + retval(2) = new octave_galois (code); + + return retval; +} + +/* +%% Test input validation +%!error rsdec () +%!error rsdec (1) +%!error rsdec (1, 2) +%!error rsdec (1, 2, 3, 4, 5, 6) +*/ + +// PKG_ADD: autoload ("bchenco", "gf.oct"); +// PKG_DEL: autoload ("bchenco", "gf.oct", "remove"); +DEFUN_DLD (bchenco, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{code} =} bchenco (@var{msg}, @var{n}, @var{k})\n\ +@deftypefnx {Loadable Function} {@var{code} =} bchenco (@var{msg}, @var{n}, @var{k}, @var{g})\n\ +@deftypefnx {Loadable Function} {@var{code} =} bchenco (@dots{}, @var{parpos})\n\ +Encodes the message @var{msg} using a [@var{n},@var{k}] BCH coding.\n\ +The variable @var{msg} is a binary array with @var{k} columns and an\n\ +arbitrary number of rows. Each row of @var{msg} represents a single symbol\n\ +to be coded by the BCH coder. The coded message is returned in the binary\n\ +array @var{code} containing @var{n} columns and the same number of rows as\n\ +@var{msg}.\n\ +\n\ +The use of @code{bchenco} can be seen in the following short example.\n\ +\n\ +@example\n\ +m = 3; n = 2^m -1; k = 4;\n\ +msg = randint (10,k);\n\ +code = bchenco (msg, n, k);\n\ +@end example\n\ +\n\ +Valid codes can be found using @code{bchpoly}. In general the codeword\n\ +length @var{n} should be of the form @code{2^@var{m}-1}, where m is an\n\ +integer. However, shortened BCH codes can be used such that if\n\ +@code{[2^@var{m}-1,@var{k}]} is a valid code\n\ +@code{[2^@var{m}-1-@var{x},@var{k}-@var{x}]}\n is also a valid code using\n\ +the same generator polynomial.\n\ +\n\ +By default the generator polynomial used in the BCH coding is\n\ +based on the properties of the Galois Field GF(2^@var{m}). This\n\ +default generator polynomial can be overridden by a polynomial in @var{g}.\n\ +Suitable generator polynomials can be constructed with @code{bchpoly}.\n\ +\n\ +By default the parity symbols are placed at the beginning of the coded\n\ +message. The variable @var{parpos} controls this positioning and can take\n\ +the values @code{\"beginning\"} or @code{\"end\"}.\n\ +@seealso{bchpoly, bchdeco, encode}\n\ +@end deftypefn") +{ + octave_value retval; + int nargin = args.length (); + + if (nargin < 3 || nargin > 5) + { + print_usage (); + return retval; + } + + Matrix msg = args(0).matrix_value (); + int nsym = msg.rows (); + int nn = args(1).nint_value (); + int k = args(2).nint_value (); + + int m = 1; + while (nn > (1< __OCTAVE_GALOIS_MAX_M)) + { + error ("bchenco: invalid values of message or codeword length"); + return retval; + } + + galois genpoly; + bool have_genpoly = false; + bool parity_at_end = false; + + for (int i = 3; i < nargin; i++) + { + if (args(i).is_string ()) + { + std::string parstr = args(i).string_value (); + for (int j = 0; j < (int)parstr.length (); j++) + parstr[j] = toupper (parstr[j]); + + if (!parstr.compare("END")) + { + parity_at_end = true; + } + else if (!parstr.compare("BEGINNING")) + { + parity_at_end = false; + } + else + { + error ("bchenco: unrecoginized parity position"); + return retval; + } + } + else + { + have_genpoly = true; + genpoly = galois (args(i).matrix_value (), m); + if (genpoly.cols () > genpoly.rows ()) + genpoly = genpoly.transpose (); + + if (genpoly.cols () != 1) + { + error ("bchenco: the generator polynomial must be a vector"); + return retval; + } + + if (genpoly.rows () != nn-k+1) + { + error ("bchenco: generator polynomial has incorrect order"); + return retval; + } + } + } + + if (!have_genpoly) + { + // The code below is basically bchpoly.m in C++, so if there is a need + // it can be used to rewrite bchpoly as an oct-file... + + RowVector found (n, 0); + found(0) = 1; + galois c (1, m, 0, m); + c(0, 0) = c.index_of (1); + Array cs (dim_vector (1, 1), 1); + + int nc = 1; + + // Find the cyclotomic cosets of GF(2^m) + while (found.min () == 0) + { + int idx = n; + for (int i = 0; i idx) + { + c(nc, cs(nc)) = r; + found(c.alpha_to (r)-1) = 1; + cs(nc) += 1; + } + nc++; + } + + // Re-use the found vector with 1==not-found !!! + found.resize (nc); + + galois f (1, 0, 0, m); + int t = 0; + int nf = 0; + do + { + t++; + for (int i = 0; i < nc; i++) + { + if (found(i) == 1) + { + for (int j = 2*(t-1); j<2*t; j++) + { + int flag = 0; + for (int l = 0; l < cs(i); l++) + { + if (c(i, l) == j+1) + { + f.resize (dim_vector (1, nf+cs(i))); + for (int ll = 0; ll < cs(i); ll++) + f(0, nf+ll) = c(i, ll); + found(i) = 0; + nf += cs(i); + flag = 1; + break; + } + } + if (flag) break; + } + } + } + } + while (nf < nn - k); + + if (nf != nn - k) + { + error ("bchenco: can not find valid generator polynomial for parameters"); + return retval; + } + + // Create polynomial of right length. + genpoly = galois (nf+1, 1, 0, m); + + genpoly(0, 0) = 1; + for (int i = 0; i < nf; i++) + { + genpoly(i+1, 0) = 1; + + // Multiply genpoly by @**(root + x) + for (int l = i; l > 0; l--) + { + if (genpoly(l, 0) != 0) + genpoly(l, 0) = genpoly(l-1, 0) + ^ genpoly.alpha_to (modn (genpoly.index_of (genpoly(l, 0)) + f(0, i), + m, n)); + else + genpoly(l, 0) = genpoly(l-1, 0); + } + // genpoly(0,0) can never be zero + genpoly(0, 0) = genpoly.alpha_to (modn (genpoly.index_of (genpoly(0, 0)) + + f(0, i), + m, n)); + } + } + + // Add space for parity block + msg.resize (nsym, nn, 0); + + // The code below basically finds the parity bits by treating the + // message as a polynomial and dividing it by the generator polynomial. + // The parity bits are then the remainder of this division. + // + // This code could just as easily be written as + // [ignore par] = gdeconv(gf(msg), gf(genpoly)); + // But the code below has the advantage of being 20 times faster :-) + + if (parity_at_end) + { + for (int l = 0; l < nsym; l++) + { + for (int i = 0; i < k; i++) + { + int feedback = (int)msg(l, i) ^ (int)msg(l, k); + if (feedback != 0) + { + for (int j = 0; j < nn-k-1; j++) + if (genpoly(nn-k-j-1, 0) != 0) + msg(l, k+j) = (int)msg(l, k+j+1) ^ feedback; + else + msg(l, k+j) = msg(l, k+j+1); + msg(l, nn-1) = genpoly(0, 0) & feedback; + } + else + { + for (int j = k; j < nn-1; j++) + msg(l, j) = msg(l, j+1); + msg(l, nn-1) = 0; + } + } + } + } + else + { + for (int l = 0; l < nsym; l++) + { + for (int i=k; i > 0; i--) + msg(l, i+nn-k-1) = msg(l, i-1); + for (int i = 0; i= 0; i--) + { + int feedback = (int)msg(l, nn-k+i) ^ (int)msg(l, nn-k-1); + if (feedback != 0) + { + for (int j = nn - k -1; j > 0; j--) + if (genpoly(j, 0) != 0) + msg(l, j) = (int)msg(l, j-1) ^ feedback; + else + msg(l, j) = msg(l, j-1); + msg(l, 0) = genpoly(0, 0) & feedback; + } + else + { + for (int j = nn - k - 1; j > 0; j--) + msg(l, j) = msg(l, j-1); + msg(l, 0) = 0; + } + } + } + } + + retval = msg; + return retval; +} + +/* +%% Test input validation +%!error bchenco () +%!error bchenco (1) +%!error bchenco (1, 2) +%!error bchenco (1, 2, 3, 4, 5, 6) +*/ + +// PKG_ADD: autoload ("bchdeco", "gf.oct"); +// PKG_DEL: autoload ("bchdeco", "gf.oct", "remove"); +DEFUN_DLD (bchdeco, args, , + "-*- texinfo -*-\n\ +@deftypefn {Loadable Function} {@var{msg} =} bchdeco (@var{code}, @var{k}, @var{t})\n\ +@deftypefnx {Loadable Function} {@var{msg} =} bchdeco (@var{code}, @var{k}, @var{t}, @var{prim})\n\ +@deftypefnx {Loadable Function} {@var{msg} =} bchdeco (@dots{}, @var{parpos})\n\ +@deftypefnx {Loadable Function} {[@var{msg}, @var{err}] =} bchdeco (@dots{})\n\ +@deftypefnx {Loadable Function} {[@var{msg}, @var{err}, @var{ccode}] =} bchdeco (@dots{})\n\ +Decodes the coded message @var{code} using a BCH coder. The message length\n\ +of the coder is defined in variable @var{k}, and the error correction\n\ +capability of the code is defined in @var{t}.\n\ +\n\ +The variable @var{code} is a binary array with @var{n} columns and an\n\ +arbitrary number of rows. Each row of @var{code} represents a single symbol\n\ +to be decoded by the BCH coder. The decoded message is returned in the\n\ +binary array @var{msg} containing @var{k} columns and the same number of\n\ +rows as @var{code}.\n\ +\n\ +The use of @code{bchdeco} can be seen in the following short example.\n\ +\n\ +@example\n\ +m = 3; n = 2^m -1; k = 4; t = 1;\n\ +msg = randint (10, k);\n\ +code = bchenco (msg, n, k);\n\ +noisy = mod (randerr (10,n) + code, 2);\n\ +[dec, err] = bchdeco (msg, k, t);\n\ +@end example\n\ +\n\ +Valid codes can be found using @code{bchpoly}. In general the codeword\n\ +length @var{n} should be of the form @code{2^@var{m}-1}, where m is an\n\ +integer. However, shortened BCH codes can be used such that if\n\ +@code{[2^@var{m}-1,@var{k}]} is a valid code\n\ +@code{[2^@var{m}-1-@var{x},@var{k}-@var{x}]}\n is also a valid code using\n\ +the same generator polynomial.\n\ +\n\ +By default the BCH coding is based on the properties of the Galois\n\ +Field GF(2^@var{m}). The primitive polynomial used in the Galois\n\ +can be overridden by a primitive polynomial in @var{prim}. Suitable\n\ +primitive polynomials can be constructed with @code{primpoly}. The form\n\ +of @var{prim} maybe be either a integer representation of the primitive\n\ +polynomial as given by @code{primpoly}, or a binary representation that\n\ +might be constructed like\n\ +\n\ +@example\n\ +m = 3;\n\ +prim = de2bi (primpoly (m));\n\ +@end example\n\ +\n\ +By default the parity symbols are assumed to be placed at the beginning of\n\ +the coded message. The variable @var{parpos} controls this positioning and\n\ +can take the values @code{\"beginning\"} or @code{\"end\"}.\n\ +@seealso{bchpoly, bchenco, decode, primpoly}\n\ +@end deftypefn") +{ + octave_value_list retval; + int nargin = args.length (); + + if (nargin < 3 || nargin > 5) + { + print_usage (); + return retval; + } + + Matrix code = args(0).matrix_value (); + int nsym = code.rows (); + int nn = code.cols (); + int k = args(1).nint_value (); + int t = args(2).nint_value (); + int t2 = t << 1; + + int m = 1; + while (nn > (1< __OCTAVE_GALOIS_MAX_M)) + { + error ("bchdeco: invalid values of message or codeword length"); + return retval; + } + + int prim = 0; // primitve polynomial of zero flags default + bool parity_at_end = false; + + for (int i = 3; i < nargin; i++) + { + if (args(i).is_string ()) + { + std::string parstr = args(i).string_value (); + for (int j = 0; j < (int)parstr.length (); j++) + parstr[j] = toupper (parstr[j]); + + if (!parstr.compare("END")) + { + parity_at_end = true; + } + else if (!parstr.compare("BEGINNING")) + { + parity_at_end = false; + } + else + { + error ("bchdeco: unrecoginized parity position"); + return retval; + } + } + else + { + if (args(i).is_real_scalar ()) + prim = args(i).int_value (); + else + { + Matrix tmp = args(i).matrix_value (); + + if (tmp.cols () > tmp.rows ()) + tmp = tmp.transpose (); + + if (tmp.cols () != 1) + { + error ("bchdeco: the primitve polynomial must be a scalar " + "or a vector"); + return retval; + } + + prim = 0; + for (int i = 0; i < tmp.rows (); i++) + if ((int)tmp(i, 0) & 1) + prim |= (1< s (dim_vector(t2+1, 1), 0); + bool syn_error = false; + + for (int i = 1; i <= t2; i++) + { + for (int j = 0; j < nn; j++) + { + if (parity_at_end) + { + if (code(lsym, nn-j-1) != 0) + s(i) ^= tables.alpha_to (modn (i*j, m, n)); + } + else + { + if (code(lsym, j) != 0) + s(i) ^= tables.alpha_to (modn (i*j, m, n)); + } + } + if (s(i) != 0) + syn_error = true; /* set error flag if non-zero syndrome */ + + } + + if (syn_error) + { /* if there are errors, try to correct them */ + int q, u; + Array d (dim_vector (t2+2, 1)), l(dim_vector (t2+2, 1)), + u_lu(dim_vector (t2+2, 1)), reg(dim_vector (t2+2, 1)), + elp(dim_vector (t2+2, t2+2)); + + /* convert syndrome from polynomial form to index form */ + for (int i = 1; i <= t2; i++) + s(i) = tables.index_of (s(i)); + + /* + * Compute the error location polynomial via the Berlekamp + * iterative algorithm. Following the terminology of Lin and + * Costello's book : d(u) is the 'mu'th discrepancy, where + * u='mu'+1 and 'mu' (the Greek letter!) is the step number + * ranging from -1 to 2*t (see L&C), l(u) is the degree of + * the elp at that step, and u_l(u) is the difference between + * the step number and the degree of the elp. + */ + /* initialise table entries */ + d(0) = 0; /* index form */ + d(1) = s(1); /* index form */ + elp(0, 0) = 0; /* index form */ + elp(1, 0) = 1; /* polynomial form */ + for (int i = 1; i < t2; i++) + { + elp(0, i) = n; /* index form */ + elp(1, i) = 0; /* polynomial form */ + } + l(0) = 0; + l(1) = 0; + u_lu(0) = -1; + u_lu(1) = 0; + u = 0; + + do + { + u++; + if (d(u) == n) + { + l(u + 1) = l(u); + for (int i = 0; i <= l(u); i++) + { + elp(u + 1, i) = elp(u, i); + elp(u, i) = tables.index_of (elp(u, i)); + } + } + else + /* + * search for words with greatest u_lu(q) for + * which d(q)!=0 + */ + { + q = u - 1; + while ((d(q) == n) && (q > 0)) + q--; + /* have found first non-zero d(q) */ + if (q > 0) + { + int j = q; + do + { + j--; + if ((d(j) != n) && (u_lu(q) < u_lu(j))) + q = j; + } + while (j > 0); + } + + /* + * have now found q such that d(u)!=0 and + * u_lu(q) is maximum + */ + /* store degree of new elp polynomial */ + if (l(u) > l(q) + u - q) + l(u + 1) = l(u); + else + l(u + 1) = l(q) + u - q; + + /* form new elp(x) */ + for (int i = 0; i < t2; i++) + elp(u + 1, i) = 0; + for (int i = 0; i <= l(q); i++) + if (elp(q, i) != n) + elp(u + 1, i + u - q) = + tables.alpha_to (modn ((d(u) + n - d(q) + elp(q, i)), m, n)); + for (int i = 0; i <= l(u); i++) + { + elp(u + 1, i) ^= elp(u, i); + elp(u, i) = tables.index_of (elp(u, i)); + } + } + u_lu(u + 1) = u - l(u + 1); + + /* form (u+1)th discrepancy */ + if (u < t2) + { + /* no discrepancy computed on last iteration */ + d(u + 1) = tables.alpha_to (s(u + 1)); + + for (int i = 1; i <= l(u + 1); i++) + if ((s(u + 1 - i) != n) && (elp(u + 1, i) != 0)) + d(u + 1) ^= tables.alpha_to (modn (s(u + 1 - i) + + tables.index_of (elp(u + 1, i)), + m, n)); + /* put d(u+1) into index form */ + d(u + 1) = tables.index_of (d(u + 1)); + } + } + while ((u < t2) && (l(u + 1) <= t)); + + u++; + if (l(u) <= t) + {/* Can correct errors */ + int count; + Array loc (dim_vector (t+2, 1)); + + /* put elp into index form */ + for (int i = 0; i <= l(u); i++) + elp(u, i) = tables.index_of (elp(u, i)); + + /* Chien search: find roots of the error location polynomial */ + for (int i = 1; i <= l(u); i++) + reg(i) = elp(u, i); + count = 0; + for (int i = 1; i <= n; i++) + { + q = 1; + for (int j = 1; j <= l(u); j++) + if (reg(j) != n) + { + reg(j) = modn ((reg(j) + j), m, n); + q ^= tables.alpha_to (reg(j)); + } + if (!q) + { /* store root and error + * location number indices */ + loc(count) = n - i; + count++; + if (count > l(u)) + break; + } + } + + if (count == l(u)) + { + /* no. roots = degree of elp hence <= t errors */ + nerr(lsym) = l(u); + for (int i = 0; i < l(u); i++) + if (parity_at_end) + code(lsym, nn-loc(i)-1) = + (int)code(lsym, nn-loc(i)-1) ^ 1; + else + code(lsym, loc(i)) = (int)code(lsym, loc(i)) ^ 1; + } + else /* elp has degree >t hence cannot solve */ + nerr(lsym) = -1; + } + else + nerr(lsym) = -1; + } + } + + Matrix msg (nsym, k); + if (parity_at_end) + { + for (int l = 0; l < nsym; l++) + for (int i = 0; i < k; i++) + msg(l, i) = code(l, i); + } + else + { + for (int l = 0; l < nsym; l++) + for (int i = 0; i < k; i++) + msg(l, i) = code(l, nn-k+i); + } + + retval(0) = octave_value (msg); + retval(1) = octave_value (nerr); + retval(2) = octave_value (code); + return retval; +} + +/* +%% Test input validation +%!error bchdeco () +%!error bchdeco (1) +%!error bchdeco (1, 2) +%!error bchdeco (1, 2, 3, 4, 5, 6) +*/ diff --git a/src/isprimitive.cc b/src/isprimitive.cc new file mode 100644 index 0000000..d8a33f7 --- /dev/null +++ b/src/isprimitive.cc @@ -0,0 +1,157 @@ +//Copyright (C) 2003 David Bateman +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of the +// License, or (at your option) any later version. +// +// This program 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 +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, see +// . +// +// In addition to the terms of the GPL, you are permitted to link this +// program with any Open Source program, as defined by the Open Source +// Initiative (www.opensource.org) + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include + +static bool +do_isprimitive (const int& a, const int& m) +{ + // Fast return since primitive polynomial can't be even + if (!(a & 1)) + return false; + + RowVector repr (1< 24) + { + error ("isprimitive: order of the primitive polynomial must " + "be less than 22"); + return retval; + } + + Matrix b (a.rows (), 1); + + for (int i = 0; i < a.rows (); i++) + { + int tmp = (int)a(i, 0); + for (int j = 1; j < a.columns (); j++) + tmp = (tmp << 1) | (int)a(i, j); + + int m = 1; + while (tmp > (1<<(m+1))) + m++; + + b(i, 0) = do_isprimitive (tmp, m); + } + retval = octave_value (b); + } + else + { + for (int i = 0; i < a.rows (); i++) + for (int j = 0; j < a.columns (); j++) + if (a(i, j) > (1<<23)) + { + error ("isprimitive: order of the primitive polynomial must " + "be less than 22"); + return retval; + } + + Matrix b (a.rows (), a.columns ()); + + for (int i = 0; i < a.rows (); i++) + { + for (int j = 0; j < a.columns (); j++) + { + int m = 1; + while (a(i, j) > (1<<(m+1))) + m++; + + b(i, j) = do_isprimitive ((int)a(i, j), m); + } + } + retval = octave_value (b); + } + + return retval; +} + +/* +%% Test input validation +%!error isprimitive () +%!error isprimitive (1, 2) +*/ + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/m4/octave-forge.m4 b/src/m4/octave-forge.m4 new file mode 100644 index 0000000..e91711f --- /dev/null +++ b/src/m4/octave-forge.m4 @@ -0,0 +1,93 @@ +# Copyright (C) 2017-2018 Olaf Till +# Modifications to print what is searching for by JohnD +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program 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 +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . + +# arguments of OF_OCTAVE_ALT_SYMS (see also description of +# OF_OCTAVE_LIST_ALT_SYMS below): +# +# $1: symbol version 1 +# $2: symbol version 2 +# $3: test for symbol version 2 +# $4: macro name to access alternative symbols +# $5: include directives for symbol version 1 +# $6: include directives for symbol version 2 +# (a list of lists of args 1--6 is $1 of OF_OCTAVE_LIST_ALT_SYMS) +# $7: name of generated include file with alternatives of Octave headers +# (arg7 is $2 of OF_OCTAVE_LIST_ALT_SYMS) +AC_DEFUN([OF_OCTAVE_ALT_SYMS], [ +AC_MSG_CHECKING([$1 or $2]) + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM([[#include ] + $6], + [$3])], + [AC_DEFINE($4, + [[$2]], + [macro for alternative Octave symbols]) + AC_MSG_RESULT([$2]) + echo '$6' >> $7], + [AC_DEFINE($4, + [[$1]], + [macro for alternative Octave symbols]) + AC_MSG_RESULT([$1]) + echo '$5' >> $7] +) +]) + + +# OF_OCTAVE_LIST_ALT_SYMS is called in the following way: +# +# OF_OCTAVE_LIST_ALT_SYMS([ +# [dnl +# [old_octave_symbol], +# [new_octave_symbol], +# [[compilation test] +# [for new_octave_symbol]], +# [NAME_OF_GENERATED_MACRO____WILL_EXPAND_TO_OLD_OR_NEW_SYMBOL], +# [[include directives] +# [except #include ] +# [necessary to compile with old_octave_symbol]], +# [[include directives] +# [except #include ] +# [nessary to compile with new_octave_symbol] +# [and to compile the test]] +# ], +# +# ... further such lists as the above +# +# ], +# +# [name-of-header-file-for-alternative-octave-iclude-directives.h]) +# +# +# This file should be put into src/m4/, and the line +# +# AC_CONFIG_MACRO_DIRS([m4]) +# +# should be put into src/configure.ac. The package should use +# autoheader to generate config.h.in (src/bootstrap should contain the +# lines 'aclocal', 'autoconf', and 'autoheader -f'). Package code +# should include config.h and use the generated macros to access the +# alternative symbols of Octave. An example of a call to +# OF_OCTAVE_LIST_ALT_SYMS in src/configure.ac is available together +# with this file. +AC_DEFUN([OF_OCTAVE_LIST_ALT_SYMS], [ + +echo '/* generated by configure */' > $2 + +m4_foreach([it], [$1], [m4_apply([OF_OCTAVE_ALT_SYMS], [it, $2])]) + +AH_BOTTOM([#include "$2"]) + +]) diff --git a/src/op-gm-gm.cc b/src/op-gm-gm.cc new file mode 100644 index 0000000..f472010 --- /dev/null +++ b/src/op-gm-gm.cc @@ -0,0 +1,168 @@ +//Copyright (C) 2003 David Bateman +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of the +// License, or (at your option) any later version. +// +// This program 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 +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, see +// . +// +// In addition to the terms of the GPL, you are permitted to link this +// program with any Open Source program, as defined by the Open Source +// Initiative (www.opensource.org) + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#ifdef HAVE_OCTAVE_OVL_H +#include +#elif HAVE_OCTAVE_OCT_OBJ_H +#include +#endif +#include + +#include "galois.h" +#include "ov-galois.h" +#include "galois-ops.h" + +// galois unary ops. + +DEFUNOP_OP (not, galois, !) + +DEFUNOP (uminus, galois) +{ + CAST_UNOP_ARG (const octave_galois&); + + // Unitary minus of Galois Field is itself!! + return new octave_galois (v.galois_value ()); +} + +DEFUNOP (uplus, galois) +{ + CAST_UNOP_ARG (const octave_galois&); + + return new octave_galois (v.galois_value ()); +} + +DEFUNOP (transpose, galois) +{ + CAST_UNOP_ARG (const octave_galois&); + + return new octave_galois (v.galois_value ().transpose ()); +} + +// galois by galois ops. + +DEFBINOP_OP_G (add, galois, galois, +) +DEFBINOP_OP_G (sub, galois, galois, -) +DEFBINOP_OP_G (mul, galois, galois, *) +DEFBINOP_FN_G (div, galois, galois, xdiv) +DEFBINOP_FN_G (pow, galois, galois, pow) +DEFBINOP_FN_G (ldiv, galois, galois, xleftdiv) + +DEFBINOP_FN (lt, galois, galois, mx_el_lt) +DEFBINOP_FN (le, galois, galois, mx_el_le) +DEFBINOP_FN (eq, galois, galois, mx_el_eq) +DEFBINOP_FN (ge, galois, galois, mx_el_ge) +DEFBINOP_FN (gt, galois, galois, mx_el_gt) +DEFBINOP_FN (ne, galois, galois, mx_el_ne) + +DEFBINOP_FN_G (el_mul, galois, galois, product) +DEFBINOP_FN_G (el_div, galois, galois, quotient) +DEFBINOP_FN_G (el_pow, galois, galois, elem_pow) + +DEFBINOP (el_ldiv, galois, galois) +{ + CAST_BINOP_ARGS (const octave_galois&, const octave_galois&); + + return new octave_galois (quotient (v2.galois_value (), v1.galois_value ())); +} + +DEFBINOP_FN (el_and, galois, galois, mx_el_and) +DEFBINOP_FN (el_or, galois, galois, mx_el_or) + +DEFCATOP_G_METHOD (gm_gm, galois, galois, concat) + +DEFASSIGNOP_FN (assign, galois, galois, assign) + +#ifndef DEFMETHOD_DLD +void +install_gm_gm_ops (void) +{ + INSTALL_UNOP (op_not, octave_galois, not); + INSTALL_UNOP (op_uminus, octave_galois, uminus); + INSTALL_UNOP (op_uplus, octave_galois, uplus); + INSTALL_UNOP (op_transpose, octave_galois, transpose); + INSTALL_UNOP (op_hermitian, octave_galois, transpose); + + INSTALL_BINOP (op_add, octave_galois, octave_galois, add); + INSTALL_BINOP (op_sub, octave_galois, octave_galois, sub); + INSTALL_BINOP (op_mul, octave_galois, octave_galois, mul); + INSTALL_BINOP (op_div, octave_galois, octave_galois, div); + INSTALL_BINOP (op_pow, octave_galois, octave_galois, pow); + INSTALL_BINOP (op_ldiv, octave_galois, octave_galois, ldiv); + INSTALL_BINOP (op_lt, octave_galois, octave_galois, lt); + INSTALL_BINOP (op_le, octave_galois, octave_galois, le); + INSTALL_BINOP (op_eq, octave_galois, octave_galois, eq); + INSTALL_BINOP (op_ge, octave_galois, octave_galois, ge); + INSTALL_BINOP (op_gt, octave_galois, octave_galois, gt); + INSTALL_BINOP (op_ne, octave_galois, octave_galois, ne); + INSTALL_BINOP (op_el_mul, octave_galois, octave_galois, el_mul); + INSTALL_BINOP (op_el_div, octave_galois, octave_galois, el_div); + INSTALL_BINOP (op_el_pow, octave_galois, octave_galois, el_pow); + INSTALL_BINOP (op_el_ldiv, octave_galois, octave_galois, el_ldiv); + INSTALL_BINOP (op_el_and, octave_galois, octave_galois, el_and); + INSTALL_BINOP (op_el_or, octave_galois, octave_galois, el_or); + + INSTALL_G_CATOP (octave_galois, octave_galois, gm_gm); + + INSTALL_ASSIGNOP (op_asn_eq, octave_galois, octave_galois, assign); +} +#else +void +install_gm_gm_ops (octave::type_info& ti) +{ + INSTALL_UNOP_TI (ti, op_not, octave_galois, not); + INSTALL_UNOP_TI (ti, op_uminus, octave_galois, uminus); + INSTALL_UNOP_TI (ti, op_uplus, octave_galois, uplus); + INSTALL_UNOP_TI (ti, op_transpose, octave_galois, transpose); + INSTALL_UNOP_TI (ti, op_hermitian, octave_galois, transpose); + + INSTALL_BINOP_TI (ti, op_add, octave_galois, octave_galois, add); + INSTALL_BINOP_TI (ti, op_sub, octave_galois, octave_galois, sub); + INSTALL_BINOP_TI (ti, op_mul, octave_galois, octave_galois, mul); + INSTALL_BINOP_TI (ti, op_div, octave_galois, octave_galois, div); + INSTALL_BINOP_TI (ti, op_pow, octave_galois, octave_galois, pow); + INSTALL_BINOP_TI (ti, op_ldiv, octave_galois, octave_galois, ldiv); + INSTALL_BINOP_TI (ti, op_lt, octave_galois, octave_galois, lt); + INSTALL_BINOP_TI (ti, op_le, octave_galois, octave_galois, le); + INSTALL_BINOP_TI (ti, op_eq, octave_galois, octave_galois, eq); + INSTALL_BINOP_TI (ti, op_ge, octave_galois, octave_galois, ge); + INSTALL_BINOP_TI (ti, op_gt, octave_galois, octave_galois, gt); + INSTALL_BINOP_TI (ti, op_ne, octave_galois, octave_galois, ne); + INSTALL_BINOP_TI (ti, op_el_mul, octave_galois, octave_galois, el_mul); + INSTALL_BINOP_TI (ti, op_el_div, octave_galois, octave_galois, el_div); + INSTALL_BINOP_TI (ti, op_el_pow, octave_galois, octave_galois, el_pow); + INSTALL_BINOP_TI (ti, op_el_ldiv, octave_galois, octave_galois, el_ldiv); + INSTALL_BINOP_TI (ti, op_el_and, octave_galois, octave_galois, el_and); + INSTALL_BINOP_TI (ti, op_el_or, octave_galois, octave_galois, el_or); + + INSTALL_CATOP_TI (ti, octave_galois, octave_galois, gm_gm); + + INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_galois, octave_galois, assign); +} +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/op-gm-m.cc b/src/op-gm-m.cc new file mode 100644 index 0000000..5a1581a --- /dev/null +++ b/src/op-gm-m.cc @@ -0,0 +1,143 @@ +//Copyright (C) 2003 David Bateman +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of the +// License, or (at your option) any later version. +// +// This program 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 +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, see +// . +// +// In addition to the terms of the GPL, you are permitted to link this +// program with any Open Source program, as defined by the Open Source +// Initiative (www.opensource.org) + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include + +#include "galois.h" +#include "ov-galois.h" +#include "galois-ops.h" + +// galois by matrix ops. + +DEFBINOP_OP_G (add, galois, matrix, +) +DEFBINOP_OP_G (sub, galois, matrix, -) + +DEFBINOP_OP_G (mul, galois, matrix, *) +DEFBINOP_FN_G (div, galois, matrix, xdiv) + +DEFBINOPX (pow, galois, matrix) +{ + error ("for A^x, A must be square and x scalar"); + return octave_value (); +} + +DEFBINOP_FN_G (ldiv, galois, matrix, xleftdiv) + +DEFBINOP_FN (lt, galois, matrix, mx_el_lt) +DEFBINOP_FN (le, galois, matrix, mx_el_le) +DEFBINOP_FN (eq, galois, matrix, mx_el_eq) +DEFBINOP_FN (ge, galois, matrix, mx_el_ge) +DEFBINOP_FN (gt, galois, matrix, mx_el_gt) +DEFBINOP_FN (ne, galois, matrix, mx_el_ne) + +DEFBINOP_FN_G (el_mul, galois, matrix, product) +DEFBINOP_FN_G (el_div, galois, matrix, quotient) +DEFBINOP_FN_G (el_pow, galois, matrix, elem_pow) + +DEFBINOP (el_ldiv, galois, matrix) +{ + CAST_BINOP_ARGS (const octave_galois&, const octave_matrix&); + + return new octave_galois (quotient (v2.matrix_value (), v1.galois_value ())); +} + +DEFBINOP_FN (el_and, galois, matrix, mx_el_and) +DEFBINOP_FN (el_or, galois, matrix, mx_el_or) + +DEFCATOP_G_METHOD (gm_m, galois, matrix, concat) + +// Need to create temporary Galois array so that matrix values are checked +DEFASSIGNOP (assign, galois, matrix) +{ + CAST_BINOP_ARGS (octave_galois&, const octave_matrix&); + + v1.assign (idx, galois (v2.matrix_value (), v1.galois_value ().m (), + v1.galois_value ().primpoly ())); + return octave_value (); +} + +#ifndef DEFMETHOD_DLD +void +install_gm_m_ops (void) +{ + INSTALL_BINOP (op_add, octave_galois, octave_matrix, add); + INSTALL_BINOP (op_sub, octave_galois, octave_matrix, sub); + INSTALL_BINOP (op_mul, octave_galois, octave_matrix, mul); + INSTALL_BINOP (op_div, octave_galois, octave_matrix, div); + INSTALL_BINOP (op_pow, octave_galois, octave_matrix, pow); + INSTALL_BINOP (op_ldiv, octave_galois, octave_matrix, ldiv); + INSTALL_BINOP (op_lt, octave_galois, octave_matrix, lt); + INSTALL_BINOP (op_le, octave_galois, octave_matrix, le); + INSTALL_BINOP (op_eq, octave_galois, octave_matrix, eq); + INSTALL_BINOP (op_ge, octave_galois, octave_matrix, ge); + INSTALL_BINOP (op_gt, octave_galois, octave_matrix, gt); + INSTALL_BINOP (op_ne, octave_galois, octave_matrix, ne); + INSTALL_BINOP (op_el_mul, octave_galois, octave_matrix, el_mul); + INSTALL_BINOP (op_el_div, octave_galois, octave_matrix, el_div); + INSTALL_BINOP (op_el_pow, octave_galois, octave_matrix, el_pow); + INSTALL_BINOP (op_el_ldiv, octave_galois, octave_matrix, el_ldiv); + INSTALL_BINOP (op_el_and, octave_galois, octave_matrix, el_and); + INSTALL_BINOP (op_el_or, octave_galois, octave_matrix, el_or); + + INSTALL_G_CATOP (octave_galois, octave_matrix, gm_m); + + INSTALL_ASSIGNOP (op_asn_eq, octave_galois, octave_matrix, assign); + INSTALL_ASSIGNCONV (octave_base_value, octave_galois, octave_matrix); +} +#else +void +install_gm_m_ops (octave::type_info& ti) +{ + INSTALL_BINOP_TI (ti, op_add, octave_galois, octave_matrix, add); + INSTALL_BINOP_TI (ti, op_sub, octave_galois, octave_matrix, sub); + INSTALL_BINOP_TI (ti, op_mul, octave_galois, octave_matrix, mul); + INSTALL_BINOP_TI (ti, op_div, octave_galois, octave_matrix, div); + INSTALL_BINOP_TI (ti, op_pow, octave_galois, octave_matrix, pow); + INSTALL_BINOP_TI (ti, op_ldiv, octave_galois, octave_matrix, ldiv); + INSTALL_BINOP_TI (ti, op_lt, octave_galois, octave_matrix, lt); + INSTALL_BINOP_TI (ti, op_le, octave_galois, octave_matrix, le); + INSTALL_BINOP_TI (ti, op_eq, octave_galois, octave_matrix, eq); + INSTALL_BINOP_TI (ti, op_ge, octave_galois, octave_matrix, ge); + INSTALL_BINOP_TI (ti, op_gt, octave_galois, octave_matrix, gt); + INSTALL_BINOP_TI (ti, op_ne, octave_galois, octave_matrix, ne); + INSTALL_BINOP_TI (ti, op_el_mul, octave_galois, octave_matrix, el_mul); + INSTALL_BINOP_TI (ti, op_el_div, octave_galois, octave_matrix, el_div); + INSTALL_BINOP_TI (ti, op_el_pow, octave_galois, octave_matrix, el_pow); + INSTALL_BINOP_TI (ti, op_el_ldiv, octave_galois, octave_matrix, el_ldiv); + INSTALL_BINOP_TI (ti, op_el_and, octave_galois, octave_matrix, el_and); + INSTALL_BINOP_TI (ti, op_el_or, octave_galois, octave_matrix, el_or); + + INSTALL_CATOP_TI (ti, octave_galois, octave_matrix, gm_m); + + INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_galois, octave_matrix, assign); + INSTALL_ASSIGNCONV_TI (ti, octave_base_value, octave_galois, octave_matrix); +} +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/op-gm-s.cc b/src/op-gm-s.cc new file mode 100644 index 0000000..573315e --- /dev/null +++ b/src/op-gm-s.cc @@ -0,0 +1,144 @@ +//Copyright (C) 2003 David Bateman +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of the +// License, or (at your option) any later version. +// +// This program 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 +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, see +// . +// +// In addition to the terms of the GPL, you are permitted to link this +// program with any Open Source program, as defined by the Open Source +// Initiative (www.opensource.org) + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include + +#include "galois.h" +#include "ov-galois.h" +#include "galois-ops.h" + +// galois by scalar ops. + +DEFBINOP_OP_G_S2 (add, galois, scalar, +) +DEFBINOP_OP_G_S2 (sub, galois, scalar, -) +DEFBINOP_FN_G_S2 (mul, galois, scalar, product) +DEFBINOP_FN_G_S2 (div, galois, scalar, quotient) + +DEFBINOP (pow, galois, scalar) +{ + CAST_BINOP_ARGS (const octave_galois&, const octave_scalar&); + + return new octave_galois (pow (v1.galois_value (), v2.double_value ())); +} + +DEFBINOP_FN_G_S2 (ldiv, galois, scalar, xleftdiv) + +DEFBINOP_FN_B_S2 (lt, galois, scalar, mx_el_lt) +DEFBINOP_FN_B_S2 (le, galois, scalar, mx_el_le) +DEFBINOP_FN_B_S2 (eq, galois, scalar, mx_el_eq) +DEFBINOP_FN_B_S2 (ge, galois, scalar, mx_el_ge) +DEFBINOP_FN_B_S2 (gt, galois, scalar, mx_el_gt) +DEFBINOP_FN_B_S2 (ne, galois, scalar, mx_el_ne) + +DEFBINOP_FN_G_S2 (el_mul, galois, scalar, product) +DEFBINOP_FN_G_S2 (el_div, galois, scalar, quotient) +DEFBINOP_FN_G (el_pow, galois, scalar, elem_pow) + +DEFBINOP (el_ldiv, galois, scalar) +{ + CAST_BINOP_ARGS (const octave_galois&, const octave_scalar&); + + return new octave_galois (quotient (v2.matrix_value (), v1.galois_value ())); +} + +DEFBINOP_FN_B_S2 (el_and, galois, scalar, mx_el_and) +DEFBINOP_FN_B_S2 (el_or, galois, scalar, mx_el_or) + +DEFCATOP (gm_s, galois, scalar) +{ + CAST_BINOP_ARGS (octave_galois&, const octave_scalar&); + return new octave_galois (v1.galois_value (). concat (v2.matrix_value (), + ra_idx)); +} + +DEFASSIGNOP (assign, galois, scalar) +{ + CAST_BINOP_ARGS (octave_galois&, const octave_scalar&); + + v1.assign (idx, galois (1, 1, v2.scalar_value (), v1.galois_value ().m (), + v1.galois_value ().primpoly ())); + return octave_value (); +} + +#ifndef DEFMETHOD_DLD +void +install_gm_s_ops (void) +{ + INSTALL_BINOP (op_add, octave_galois, octave_scalar, add); + INSTALL_BINOP (op_sub, octave_galois, octave_scalar, sub); + INSTALL_BINOP (op_mul, octave_galois, octave_scalar, mul); + INSTALL_BINOP (op_div, octave_galois, octave_scalar, div); + INSTALL_BINOP (op_pow, octave_galois, octave_scalar, pow); + INSTALL_BINOP (op_ldiv, octave_galois, octave_scalar, ldiv); + INSTALL_BINOP (op_lt, octave_galois, octave_scalar, lt); + INSTALL_BINOP (op_le, octave_galois, octave_scalar, le); + INSTALL_BINOP (op_eq, octave_galois, octave_scalar, eq); + INSTALL_BINOP (op_ge, octave_galois, octave_scalar, ge); + INSTALL_BINOP (op_gt, octave_galois, octave_scalar, gt); + INSTALL_BINOP (op_ne, octave_galois, octave_scalar, ne); + INSTALL_BINOP (op_el_mul, octave_galois, octave_scalar, el_mul); + INSTALL_BINOP (op_el_div, octave_galois, octave_scalar, el_div); + INSTALL_BINOP (op_el_pow, octave_galois, octave_scalar, el_pow); + INSTALL_BINOP (op_el_ldiv, octave_galois, octave_scalar, el_ldiv); + INSTALL_BINOP (op_el_and, octave_galois, octave_scalar, el_and); + INSTALL_BINOP (op_el_or, octave_galois, octave_scalar, el_or); + + INSTALL_G_CATOP (octave_galois, octave_scalar, gm_s); + + INSTALL_ASSIGNOP (op_asn_eq, octave_galois, octave_scalar, assign); +} +#else +void +install_gm_s_ops (octave::type_info& ti) +{ + INSTALL_BINOP_TI (ti, op_add, octave_galois, octave_scalar, add); + INSTALL_BINOP_TI (ti, op_sub, octave_galois, octave_scalar, sub); + INSTALL_BINOP_TI (ti, op_mul, octave_galois, octave_scalar, mul); + INSTALL_BINOP_TI (ti, op_div, octave_galois, octave_scalar, div); + INSTALL_BINOP_TI (ti, op_pow, octave_galois, octave_scalar, pow); + INSTALL_BINOP_TI (ti, op_ldiv, octave_galois, octave_scalar, ldiv); + INSTALL_BINOP_TI (ti, op_lt, octave_galois, octave_scalar, lt); + INSTALL_BINOP_TI (ti, op_le, octave_galois, octave_scalar, le); + INSTALL_BINOP_TI (ti, op_eq, octave_galois, octave_scalar, eq); + INSTALL_BINOP_TI (ti, op_ge, octave_galois, octave_scalar, ge); + INSTALL_BINOP_TI (ti, op_gt, octave_galois, octave_scalar, gt); + INSTALL_BINOP_TI (ti, op_ne, octave_galois, octave_scalar, ne); + INSTALL_BINOP_TI (ti, op_el_mul, octave_galois, octave_scalar, el_mul); + INSTALL_BINOP_TI (ti, op_el_div, octave_galois, octave_scalar, el_div); + INSTALL_BINOP_TI (ti, op_el_pow, octave_galois, octave_scalar, el_pow); + INSTALL_BINOP_TI (ti, op_el_ldiv, octave_galois, octave_scalar, el_ldiv); + INSTALL_BINOP_TI (ti, op_el_and, octave_galois, octave_scalar, el_and); + INSTALL_BINOP_TI (ti, op_el_or, octave_galois, octave_scalar, el_or); + + INSTALL_CATOP_TI (ti, octave_galois, octave_scalar, gm_s); + + INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_galois, octave_scalar, assign); +} +#endif +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/op-m-gm.cc b/src/op-m-gm.cc new file mode 100644 index 0000000..8935f7c --- /dev/null +++ b/src/op-m-gm.cc @@ -0,0 +1,143 @@ +//Copyright (C) 2003 David Bateman +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of the +// License, or (at your option) any later version. +// +// This program 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 +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, see +// . +// +// In addition to the terms of the GPL, you are permitted to link this +// program with any Open Source program, as defined by the Open Source +// Initiative (www.opensource.org) + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include + +#include "galois.h" +#include "ov-galois.h" +#include "galois-ops.h" + +// matrix by galois ops. + +DEFBINOP_OP_G (add, matrix, galois, +) +DEFBINOP_OP_G (sub, matrix, galois, -) + +DEFBINOP_OP_G (mul, matrix, galois, *) +DEFBINOP_FN_G (div, matrix, galois, xdiv) + +DEFBINOP (pow, matrix, galois) +{ + CAST_BINOP_ARGS (const octave_matrix&, const octave_galois&); + galois tmp (v1.matrix_value (), v2.m (), v2.primpoly ()); + + return new octave_galois (pow (tmp, v2.galois_value ())); +} + +DEFBINOP_FN_G (ldiv, matrix, galois, xleftdiv) + +DEFBINOP_FN (lt, matrix, galois, mx_el_lt) +DEFBINOP_FN (le, matrix, galois, mx_el_le) +DEFBINOP_FN (eq, matrix, galois, mx_el_eq) +DEFBINOP_FN (ge, matrix, galois, mx_el_ge) +DEFBINOP_FN (gt, matrix, galois, mx_el_gt) +DEFBINOP_FN (ne, matrix, galois, mx_el_ne) + +DEFBINOP_FN_G (el_mul, matrix, galois, product) +DEFBINOP_FN_G (el_div, matrix, galois, quotient) + +DEFBINOP (el_pow, matrix, galois) +{ + CAST_BINOP_ARGS (const octave_matrix&, const octave_galois&); + galois tmp (v1.matrix_value (), v2.m (), v2.primpoly ()); + + return new octave_galois (elem_pow (tmp, v2.galois_value ())); +} + +DEFBINOP (el_ldiv, matrix, galois) +{ + CAST_BINOP_ARGS (const octave_matrix&, const octave_galois&); + + return new octave_galois (quotient (v2.galois_value (), v1.matrix_value ())); +} + +DEFBINOP_FN (el_and, matrix, galois, mx_el_and) +DEFBINOP_FN (el_or, matrix, galois, mx_el_or) + +DEFCATOP_G_FN (m_gm, matrix, galois, concat) + +DEFASSIGNOP_FN (assign, matrix, galois, assign) + +#ifndef DEFMETHOD_DLD +void +install_m_gm_ops (void) +{ + INSTALL_BINOP (op_add, octave_matrix, octave_galois, add); + INSTALL_BINOP (op_sub, octave_matrix, octave_galois, sub); + INSTALL_BINOP (op_mul, octave_matrix, octave_galois, mul); + INSTALL_BINOP (op_div, octave_matrix, octave_galois, div); + INSTALL_BINOP (op_pow, octave_matrix, octave_galois, pow); + INSTALL_BINOP (op_ldiv, octave_matrix, octave_galois, ldiv); + INSTALL_BINOP (op_lt, octave_matrix, octave_galois, lt); + INSTALL_BINOP (op_le, octave_matrix, octave_galois, le); + INSTALL_BINOP (op_eq, octave_matrix, octave_galois, eq); + INSTALL_BINOP (op_ge, octave_matrix, octave_galois, ge); + INSTALL_BINOP (op_gt, octave_matrix, octave_galois, gt); + INSTALL_BINOP (op_ne, octave_matrix, octave_galois, ne); + INSTALL_BINOP (op_el_mul, octave_matrix, octave_galois, el_mul); + INSTALL_BINOP (op_el_div, octave_matrix, octave_galois, el_div); + INSTALL_BINOP (op_el_pow, octave_matrix, octave_galois, el_pow); + INSTALL_BINOP (op_el_ldiv, octave_matrix, octave_galois, el_ldiv); + INSTALL_BINOP (op_el_and, octave_matrix, octave_galois, el_and); + INSTALL_BINOP (op_el_or, octave_matrix, octave_galois, el_or); + + INSTALL_G_CATOP (octave_matrix, octave_galois, m_gm); + + INSTALL_ASSIGNOP (op_asn_eq, octave_matrix, octave_galois, assign); + //INSTALL_ASSIGNCONV (octave_base_value, octave_matrix, octave_galois); +} +#else +void +install_m_gm_ops (octave::type_info& ti) +{ + INSTALL_BINOP_TI (ti, op_add, octave_matrix, octave_galois, add); + INSTALL_BINOP_TI (ti, op_sub, octave_matrix, octave_galois, sub); + INSTALL_BINOP_TI (ti, op_mul, octave_matrix, octave_galois, mul); + INSTALL_BINOP_TI (ti, op_div, octave_matrix, octave_galois, div); + INSTALL_BINOP_TI (ti, op_pow, octave_matrix, octave_galois, pow); + INSTALL_BINOP_TI (ti, op_ldiv, octave_matrix, octave_galois, ldiv); + INSTALL_BINOP_TI (ti, op_lt, octave_matrix, octave_galois, lt); + INSTALL_BINOP_TI (ti, op_le, octave_matrix, octave_galois, le); + INSTALL_BINOP_TI (ti, op_eq, octave_matrix, octave_galois, eq); + INSTALL_BINOP_TI (ti, op_ge, octave_matrix, octave_galois, ge); + INSTALL_BINOP_TI (ti, op_gt, octave_matrix, octave_galois, gt); + INSTALL_BINOP_TI (ti, op_ne, octave_matrix, octave_galois, ne); + INSTALL_BINOP_TI (ti, op_el_mul, octave_matrix, octave_galois, el_mul); + INSTALL_BINOP_TI (ti, op_el_div, octave_matrix, octave_galois, el_div); + INSTALL_BINOP_TI (ti, op_el_pow, octave_matrix, octave_galois, el_pow); + INSTALL_BINOP_TI (ti, op_el_ldiv, octave_matrix, octave_galois, el_ldiv); + INSTALL_BINOP_TI (ti, op_el_and, octave_matrix, octave_galois, el_and); + INSTALL_BINOP_TI (ti, op_el_or, octave_matrix, octave_galois, el_or); + + INSTALL_CATOP_TI (ti, octave_matrix, octave_galois, m_gm); + + INSTALL_ASSIGNOP_TI (ti, op_asn_eq, octave_matrix, octave_galois, assign); + //INSTALL_ASSIGNCONV (octave_base_value, octave_matrix, octave_galois); +} +#endif +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/op-s-gm.cc b/src/op-s-gm.cc new file mode 100644 index 0000000..86b30d0 --- /dev/null +++ b/src/op-s-gm.cc @@ -0,0 +1,148 @@ +//Copyright (C) 2003 David Bateman +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of the +// License, or (at your option) any later version. +// +// This program 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 +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, see +// . +// +// In addition to the terms of the GPL, you are permitted to link this +// program with any Open Source program, as defined by the Open Source +// Initiative (www.opensource.org) + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include + +#include "galois.h" +#include "ov-galois.h" +#include "galois-ops.h" + +// scalar by galois ops. + +DEFBINOP_OP_G_S1 (add, scalar, galois, +) +DEFBINOP_OP_G_S1 (sub, scalar, galois, -) +DEFBINOP_FN_G_S1 (mul, scalar, galois, product) +DEFBINOP_FN_G_S1 (div, scalar, galois, xdiv) + +DEFBINOP (pow, scalar, galois) +{ + CAST_BINOP_ARGS (const octave_scalar&, const octave_galois&); + galois tmp (v1.matrix_value (), v2.m (), v2.primpoly ()); + + return new octave_galois (pow (tmp, v2.galois_value ())); +} + +DEFBINOP (ldiv, scalar, galois) +{ + CAST_BINOP_ARGS (const octave_scalar&, const octave_galois&); \ + + return new octave_galois (quotient (v2.galois_value (), v1.matrix_value ())); +} + +DEFBINOP_FN_B_S1 (lt, scalar, galois, mx_el_lt) +DEFBINOP_FN_B_S1 (le, scalar, galois, mx_el_le) +DEFBINOP_FN_B_S1 (eq, scalar, galois, mx_el_eq) +DEFBINOP_FN_B_S1 (ge, scalar, galois, mx_el_ge) +DEFBINOP_FN_B_S1 (gt, scalar, galois, mx_el_gt) +DEFBINOP_FN_B_S1 (ne, scalar, galois, mx_el_ne) + +DEFBINOP_FN_G_S1 (el_mul, scalar, galois, product) +DEFBINOP_FN_G_S1 (el_div, scalar, galois, quotient) + +DEFBINOP (el_pow, scalar, galois) +{ + CAST_BINOP_ARGS (const octave_scalar&, const octave_galois&); \ + galois tmp (v1.matrix_value (), v2.m (), v2.primpoly ()); + + return new octave_galois (elem_pow (tmp, v2.galois_value ())); +} + +DEFBINOP (el_ldiv, scalar, galois) +{ + CAST_BINOP_ARGS (const octave_scalar&, const octave_galois&); + + return new octave_galois (quotient (v2.galois_value (), v1.matrix_value ())); +} + +DEFBINOP_FN_B_S1 (el_and, scalar, galois, mx_el_and) +DEFBINOP_FN_B_S1 (el_or, scalar, galois, mx_el_or) + +DEFCATOP (s_gm, scalar, galois) +{ + CAST_BINOP_ARGS (octave_scalar&, const octave_galois&); + return new octave_galois (concat (v1.matrix_value (), v2.galois_value (), + ra_idx)); +} + +#ifndef DEFMETHOD_DLD +void +install_s_gm_ops (void) +{ + INSTALL_BINOP (op_add, octave_scalar, octave_galois, add); + INSTALL_BINOP (op_sub, octave_scalar, octave_galois, sub); + INSTALL_BINOP (op_mul, octave_scalar, octave_galois, mul); + INSTALL_BINOP (op_div, octave_scalar, octave_galois, div); + INSTALL_BINOP (op_pow, octave_scalar, octave_galois, pow); + INSTALL_BINOP (op_ldiv, octave_scalar, octave_galois, ldiv); + INSTALL_BINOP (op_lt, octave_scalar, octave_galois, lt); + INSTALL_BINOP (op_le, octave_scalar, octave_galois, le); + INSTALL_BINOP (op_eq, octave_scalar, octave_galois, eq); + INSTALL_BINOP (op_ge, octave_scalar, octave_galois, ge); + INSTALL_BINOP (op_gt, octave_scalar, octave_galois, gt); + INSTALL_BINOP (op_ne, octave_scalar, octave_galois, ne); + INSTALL_BINOP (op_el_mul, octave_scalar, octave_galois, el_mul); + INSTALL_BINOP (op_el_div, octave_scalar, octave_galois, el_div); + INSTALL_BINOP (op_el_pow, octave_scalar, octave_galois, el_pow); + INSTALL_BINOP (op_el_ldiv, octave_scalar, octave_galois, el_ldiv); + INSTALL_BINOP (op_el_and, octave_scalar, octave_galois, el_and); + INSTALL_BINOP (op_el_or, octave_scalar, octave_galois, el_or); + + INSTALL_G_CATOP (octave_scalar, octave_galois, s_gm); + + INSTALL_ASSIGNCONV (octave_scalar, octave_galois, octave_galois); +} +#else +void +install_s_gm_ops (octave::type_info& ti) +{ + INSTALL_BINOP_TI (ti, op_add, octave_scalar, octave_galois, add); + INSTALL_BINOP_TI (ti, op_sub, octave_scalar, octave_galois, sub); + INSTALL_BINOP_TI (ti, op_mul, octave_scalar, octave_galois, mul); + INSTALL_BINOP_TI (ti, op_div, octave_scalar, octave_galois, div); + INSTALL_BINOP_TI (ti, op_pow, octave_scalar, octave_galois, pow); + INSTALL_BINOP_TI (ti, op_ldiv, octave_scalar, octave_galois, ldiv); + INSTALL_BINOP_TI (ti, op_lt, octave_scalar, octave_galois, lt); + INSTALL_BINOP_TI (ti, op_le, octave_scalar, octave_galois, le); + INSTALL_BINOP_TI (ti, op_eq, octave_scalar, octave_galois, eq); + INSTALL_BINOP_TI (ti, op_ge, octave_scalar, octave_galois, ge); + INSTALL_BINOP_TI (ti, op_gt, octave_scalar, octave_galois, gt); + INSTALL_BINOP_TI (ti, op_ne, octave_scalar, octave_galois, ne); + INSTALL_BINOP_TI (ti, op_el_mul, octave_scalar, octave_galois, el_mul); + INSTALL_BINOP_TI (ti, op_el_div, octave_scalar, octave_galois, el_div); + INSTALL_BINOP_TI (ti, op_el_pow, octave_scalar, octave_galois, el_pow); + INSTALL_BINOP_TI (ti, op_el_ldiv, octave_scalar, octave_galois, el_ldiv); + INSTALL_BINOP_TI (ti, op_el_and, octave_scalar, octave_galois, el_and); + INSTALL_BINOP_TI (ti, op_el_or, octave_scalar, octave_galois, el_or); + + INSTALL_CATOP_TI (ti, octave_scalar, octave_galois, s_gm); + + INSTALL_ASSIGNCONV_TI (ti, octave_scalar, octave_galois, octave_galois); +} +#endif +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/ov-galois.cc b/src/ov-galois.cc new file mode 100644 index 0000000..06ae00c --- /dev/null +++ b/src/ov-galois.cc @@ -0,0 +1,864 @@ +//Copyright (C) 2003 David Bateman +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of the +// License, or (at your option) any later version. +// +// This program 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 +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, see +// . +// +// In addition to the terms of the GPL, you are permitted to link this +// program with any Open Source program, as defined by the Open Source +// Initiative (www.opensource.org) + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include +#include +#ifdef HAVE_OCTAVE_GRIPES_H +#include +#endif +#ifdef HAVE_OCTAVE_ERRWARN_H +#include +#endif +#include +#include + +#ifdef HAVE_OCTAVE_OVL_H +#include +#elif HAVE_OCTAVE_OCT_OBJ_H +#include +#endif +#include +#include + +#if defined(HAVE_OCTAVE_LS_OCT_TEXT_H) +# include +#else +# include +#endif + +#include "galois.h" +#include "ov-galois.h" + +#if defined (HAVE_HDF5) +# if defined (HAVE_HDF5_H) +# include +# endif +# if defined (HAVE_OCTAVE_OCT_HDF5_TYPES_H) +# include "oct-hdf5-types.h" +# endif +# if defined (OCTAVE_ENABLE_64) +# define H5T_NATIVE_IDX H5T_NATIVE_INT64 +# else +# define H5T_NATIVE_IDX H5T_NATIVE_INT +# endif +#endif + +#if ! defined (X_CAST) +# define X_CAST(T, E) (T) (E) +#endif + +#if defined (DEFINE_OCTAVE_ALLOCATOR) +DEFINE_OCTAVE_ALLOCATOR (octave_galois); +#endif + +DEFINE_OV_TYPEID_FUNCTIONS_AND_DATA (octave_galois, "galois", "galois"); + +octave_value +octave_galois::resize (const dim_vector& dv, bool) const +{ + if (dv.length () > 2) + { + error ("Can not resize galois structure to NDArray"); + return octave_value (); + } + galois retval (gval); + retval.resize (dv); + return new octave_galois (retval); +} + +octave_value_list +octave_galois::dotref (const octave_value_list& idx) +{ + octave_value_list retval; + + assert (idx.length () == 1); + + std::string nm = idx(0).string_value (); + + if (nm == __GALOIS_PRIMPOLY_STR) + retval(0) = octave_value ((double)gval.primpoly ()); + else if (nm == __GALOIS_ORDER_STR) + retval(0) = octave_value ((double)gval.m ()); + else if (nm == __GALOIS_DATA_STR) + { + int r = gval.rows (); + int c = gval.columns (); + Matrix data (r, c); + for (int i = 0; i < r; i++) + for (int j = 0; j < c; j++) + data(i, j) = (double)gval(i, j); + retval(0) = octave_value (data); + } +#ifdef GALOIS_DISP_PRIVATES + else if (nm == __GALOIS_LENGTH_STR) + retval(0) = octave_value ((double)gval.n ()); + else if (nm == __GALOIS_ALPHA_TO_STR) + { + int n = gval.n (); + Matrix data (n+1, 1); + for (int i = 0; i < n+1; i++) + data(i, 0) = (double)gval.alpha_to (i); + retval(0) = octave_value (data); + } + else if (nm == __GALOIS_INDEX_OF_STR) + { + int n = gval.n (); + Matrix data (n+1, 1); + for (int i = 0; i < n+1; i++) + data(i, 0) = (double)gval.index_of (i); + retval(0) = octave_value (data); + } +#endif + else + error ("galois structure has no member `%s'", nm.c_str ()); + + return retval; +} + +octave_value +octave_galois::do_index_op (const octave_value_list& idx, + bool resize_ok) +{ + octave_value retval; + + int len = idx.length (); + + switch (len) + { + case 2: + { + idx_vector i = idx (0).index_vector (); + idx_vector j = idx (1).index_vector (); + + retval = new octave_galois (gval.index (i, j, resize_ok)); + } + break; + + case 1: + { + idx_vector i = idx (0).index_vector (); + + retval = new octave_galois (gval.index (i, resize_ok)); + } + break; + + default: + { + std::string n = type_name (); + + error ("invalid number of indices (%d) for %s value", + len, n.c_str ()); + } + break; + } + + return retval; +} + +octave_value +octave_galois::subsref (const std::string &type, + const std::list& idx) +{ + octave_value retval; + + int skip = 1; + + switch (type[0]) + { + case '(': + retval = do_index_op (idx.front (), true); + break; + + case '.': + { + octave_value_list t = dotref (idx.front ()); + + retval = (t.length () == 1) ? t(0) : octave_value (t); + } + break; + + case '{': + error ("%s cannot be indexed with %c", type_name ().c_str (), type[0]); + break; + + default: + panic_impossible (); + } + + if (! error_state) + retval = retval.next_subsref (type, idx, skip); + + return retval; +} + +bool +octave_galois::is_true (void) const +{ + bool retval = false; + + if (rows () > 0 && columns () > 0) + { + boolMatrix m = (gval.all () . all ()); + + retval = (m.rows () == 1 && m.columns () == 1 && m(0, 0)); + } + + return retval; +} + +bool +octave_galois::print_as_scalar (void) const +{ + int nr = rows (); + int nc = columns (); + + return ((nr == 1 && nc == 1) || (nr == 0 || nc == 0)); +} + +void +#if defined (HAVE_OCTAVE_BASE_VALUE_PRINT_CONST) +octave_galois::print (std::ostream& os, bool) const +#else +octave_galois::print (std::ostream& os, bool) +#endif +{ + print_raw (os); +} + +void +octave_galois::print_raw (std::ostream& os, bool) const +{ + bool first = true; + int m = gval.m (); + int primpoly = gval.primpoly (); + Matrix data (gval.rows (), gval.cols ()); + + indent (os); + + if (m == 1) + os << "GF(2) array."; + else + { + os << "GF(2^" << m << ") array. Primitive Polynomial = "; + + for (int i = m; i >= 0; i--) + { + if (primpoly & (1< 0) + { + if (first) + { + first = false; + os << "D"; + } + else + os << "+D"; + if (i != 1) + os << "^" << i; + } + else + { + if (first) + { + first = false; + os << "1"; + } + else + os << "+1"; + } + } + } + os << " (decimal " << primpoly << ")"; + } + newline (os); + newline (os); + indent (os); + + os << "Array elements = "; + newline (os); + newline (os); + + for (int i = 0; i < gval.rows (); i++) + for (int j = 0; j < gval.columns (); j++) + data(i, j) = (double)gval(i, j); + + octave_print_internal (os, data, false, current_print_indent_level ()); + newline (os); +} + +bool +octave_galois::print_name_tag (std::ostream& os, const std::string& name) const +{ + bool retval = false; + + indent (os); + + // Vstruct_levels_to_print was made static in Octave 3.4, which means + // the name_tag might be printed on a seperate line when it shouldn't be. +#if 0 + if (Vstruct_levels_to_print < 0) +#else + if (false) +#endif + os << name << " = "; + else + { + os << name << " ="; + newline (os); + retval = true; + } + + return retval; +} + +void +octave_galois::print_info (std::ostream& os, const std::string& prefix) const +{ + gval.print_info (os, prefix); +} + +double +octave_galois::double_value (bool) const +{ + double retval = octave_NaN; + + if (rows () > 0 && columns () > 0) + { + OCTAVE__WARN_INVALID_CONVERSION ("Octave:array-as-scalar", + "real matrix", "real scalar"); + + retval = (double) gval (0, 0); + } + else + OCTAVE__ERR_INVALID_CONVERSION ("galois", "real scalar"); + + return retval; +} + +Complex +octave_galois::complex_value (bool) const +{ + double tmp = octave_NaN; + + Complex retval (tmp, tmp); + + if (rows () > 0 && columns () > 0) + { + OCTAVE__WARN_INVALID_CONVERSION ("Octave:array-as-scalar", + "real matrix", "real scalar"); + + retval = (double) gval (0, 0); + } + else + OCTAVE__ERR_INVALID_CONVERSION ("galois", "complex scalar"); + + return retval; +} + +Matrix +octave_galois::matrix_value (bool) const +{ + Matrix retval; + + retval.resize (rows (), columns ()); + for (int i = 0; i < rows (); i++) + for (int j = 0; j < columns (); j++) + retval(i, j) = gval(i, j); + + return retval; +} + +NDArray +octave_galois::array_value (bool) const +{ + int nr = rows (); + int nc = columns (); + dim_vector dv (nr, nc); + NDArray retval (dv); + + for (int i = 0; i < nr; i++) + for (int j = 0; j < nc; j++) + retval(i + j*nr) = gval(i, j); + + return retval; +} + +void +octave_galois::assign (const octave_value_list& idx, + const galois& rhs) +{ + int len = idx.length (); + + if (gval.have_field () && rhs.have_field ()) + { + if ((gval.m () != rhs.m ()) || (gval.primpoly () != rhs.primpoly ())) + { + (*current_liboctave_error_handler) ("can not assign data between two different Galois Fields"); + return; + } + } + + switch (len) + { + case 2: + { + idx_vector i = idx (0).index_vector (); + + if (! error_state) + { + idx_vector j = idx (1).index_vector (); + + if (! error_state) + gval.assign (i, j, rhs); + } + } + break; + + case 1: + { + idx_vector i = idx (0).index_vector (); + + if (! error_state) + gval.assign (i, rhs); + } + break; + + default: + error ("invalid number of indices (%d) for galois assignment", + len); + break; + } +} + +bool +octave_galois::save_ascii (std::ostream& os) +{ + dim_vector d = dims (); + Matrix tmp = matrix_value (); + + // Note use N-D way of writing matrix for eventual conversion + // of octave_galois to handle N-D arrays + os << "# m: " << m () << "\n"; + os << "# prim: " << primpoly () << "\n"; + os << "# ndims: " << d.length () << "\n"; + + for (int i = 0; i < d.length (); i++) + os << " " << d (i); + + os << "\n" << tmp; + return true; +} + +bool +octave_galois::load_ascii (std::istream& is) +{ + int mord, prim, mdims; + bool success = true; + + if (extract_keyword (is, "m", mord) && extract_keyword (is, "prim", prim) && + extract_keyword (is, "ndims", mdims)) + { + dim_vector dv; + dv.resize (mdims); + + for (int i = 0; i < mdims; i++) + is >> dv(i); + + if (dv.length () != 2) + { + error ("load: N-D galois matrix not supported"); + success = false; + } + else + { + + Matrix tmp (dv(0), dv(1)); + is >> tmp; + + if (!is) + { + error ("load: failed to load matrix constant"); + success = false; + } + gval = galois (tmp, mord, prim); + } + } + else + { + error ("load: failed to extract galois field order, primitive and/or imension"); + success = false; + } + + return success;; +} + +bool +octave_galois::save_binary (std::ostream& os, bool& save_as_floats) +{ + char tmp = m (); + os.write (X_CAST (char *, &tmp), 1); + int32_t itmp = primpoly (); + os.write (X_CAST (char *, &itmp), 4); + + dim_vector d = dims (); + + // Don't handle N-D arrays yet + if (d.length () != 2) + return false; + + // Use negative value for ndims to be consistent with other formats + itmp = - d.length (); + os.write (X_CAST (char *, &itmp), 4); + for (int i = 0; i < d.length (); i++) + { + itmp = d(i); + os.write (X_CAST (char *, &itmp), 4); + } + + Matrix m = matrix_value (); + save_type st; + if (tmp < 8) + st = LS_U_CHAR; + else if (tmp < 16) + st = LS_U_SHORT; + else + st = LS_U_INT; + const double *mtmp = m.data (); + write_doubles (os, mtmp, st, d.numel ()); + + return true; +} + +bool +octave_galois::load_binary (std::istream& is, bool swap, + OCTAVE_MACH_INFO_FLOAT_FORMAT fmt) +{ + char mord; + int32_t prim, mdims; + + if (! is.read (X_CAST (char *, &mord), 1)) + return false; + + if (! is.read (X_CAST (char *, &prim), 4)) + return false; + if (swap) + swap_bytes <4> (X_CAST (char *, &prim)); + + if (! is.read (X_CAST (char *, &mdims), 4)) + return false; + if (swap) + swap_bytes <4> (X_CAST (char *, &mdims)); + + // Don't treat N-D arrays yet + if (mdims == -2) + { + mdims = - mdims; + int32_t di; + dim_vector dv; + dv.resize (mdims); + + for (int i = 0; i < mdims; i++) + { + if (! is.read (X_CAST (char *, &di), 4)) + return false; + if (swap) + swap_bytes <4> (X_CAST (char *, &di)); + dv(i) = di; + } + + char tmp; + if (! is.read (X_CAST (char *, &tmp), 1)) + return false; + + Matrix m (dv(0), dv(1)); + double *re = m.fortran_vec (); + read_doubles (is, re, X_CAST (save_type, tmp), dv.numel (), swap, fmt); + if (error_state || ! is) + return false; + + gval = galois (m, mord, prim); + } + + return true; +} + +bool +octave_galois::save_hdf5 (octave_hdf5_id loc_id, const char *name, bool save_as_floats) +{ + bool retval = true; + +#if defined (HAVE_HDF5) + + Matrix mval = matrix_value (); + hid_t group_hid = -1; +#if HAVE_HDF5_18 + group_hid = H5Gcreate (loc_id, name, H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); +#else + group_hid = H5Gcreate (loc_id, name, 0); +#endif + if (group_hid < 0 ) return false; + + dim_vector d = dims (); + OCTAVE_LOCAL_BUFFER (hsize_t, hdims, d.length () > 2 ? d.length () : 3); + hid_t space_hid = -1, data_hid = -1; + char tmp; + int32_t itmp; + + space_hid = H5Screate_simple (0, hdims, (hsize_t*) 0); + if (space_hid < 0) + { + H5Gclose (group_hid); + return false; + } + +#if HAVE_HDF5_18 + data_hid = H5Dcreate (group_hid, "m", H5T_NATIVE_UCHAR, space_hid, + H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); +#else + data_hid = H5Dcreate (group_hid, "m", H5T_NATIVE_UCHAR, space_hid, + H5P_DEFAULT); +#endif + if (data_hid < 0) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + tmp = m (); + retval = H5Dwrite (data_hid, H5T_NATIVE_UCHAR, H5S_ALL, H5S_ALL, H5P_DEFAULT, + (void*) &tmp) >= 0; + H5Dclose (data_hid); + if (!retval) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + +#if HAVE_HDF5_18 + data_hid = H5Dcreate (group_hid, "prim", H5T_NATIVE_UINT, space_hid, + H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); +#else + data_hid = H5Dcreate (group_hid, "prim", H5T_NATIVE_UINT, space_hid, + H5P_DEFAULT); +#endif + if (data_hid < 0) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + itmp = primpoly (); + retval = H5Dwrite (data_hid, H5T_NATIVE_UINT, H5S_ALL, H5S_ALL, H5P_DEFAULT, + (void*) &itmp) >= 0; + H5Dclose (data_hid); + if (!retval) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + H5Sclose (space_hid); + + // Octave uses column-major, while HDF5 uses row-major ordering + for (int i = 0, j = d.length () - 1; i < d.length (); i++, j--) + hdims[i] = d (j); + + space_hid = H5Screate_simple (d.length (), hdims, (hsize_t*) 0); + if (space_hid < 0) return false; + + double *mtmp = mval.fortran_vec (); + OCTAVE_LOCAL_BUFFER (uint32_t, vtmp, d.numel ()); + + hid_t save_type_hid = H5T_NATIVE_UINT; + if (tmp <= 8) + { + save_type_hid = H5T_NATIVE_UCHAR; + char *wtmp = (char *)vtmp; + for (int i = 0; i < d.numel (); i++) + wtmp[i] = (char) mtmp[i]; + } + else if (tmp <= 16) + { + save_type_hid = H5T_NATIVE_USHORT; + uint16_t *wtmp = (uint16_t *)vtmp; + for (int i = 0; i < d.numel (); i++) + wtmp[i] = (uint16_t) mtmp[i]; + } + else + { + for (int i = 0; i < d.numel (); i++) + vtmp[i] = (uint32_t) mtmp[i]; + } + +#if HAVE_HDF5_18 + data_hid = H5Dcreate (group_hid, "val", save_type_hid, space_hid, + H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT); +#else + data_hid = H5Dcreate (group_hid, "val", save_type_hid, space_hid, + H5P_DEFAULT); +#endif + if (data_hid < 0) + { + H5Sclose (space_hid); + H5Gclose (group_hid); + return false; + } + + retval = H5Dwrite (data_hid, save_type_hid, H5S_ALL, H5S_ALL, + H5P_DEFAULT, (void*) vtmp) >= 0; + + H5Dclose (data_hid); + H5Sclose (space_hid); + H5Gclose (group_hid); + +#elif defined (HAVE_OCTAVE_BASE_VALUE_GRIPE_LOAD_SAVE) + gripe_save ("hdf5"); +#else + warning ("galois: saving hdf5 files not available"); +#endif + + return retval; +} + +bool +octave_galois::load_hdf5 (octave_hdf5_id loc_id, const char *name) +{ + bool retval = false; + +#if defined (HAVE_HDF5) + + char mord; + unsigned int prim; + hid_t group_hid, data_hid, space_id; + hsize_t rank; + +#if HAVE_HDF5_18 + group_hid = H5Gopen (loc_id, name, H5P_DEFAULT); +#else + group_hid = H5Gopen (loc_id, name); +#endif + if (group_hid < 0 ) return false; + +#if HAVE_HDF5_18 + data_hid = H5Dopen (group_hid, "m", H5P_DEFAULT); +#else + data_hid = H5Dopen (group_hid, "m"); +#endif + space_id = H5Dget_space (data_hid); + rank = H5Sget_simple_extent_ndims (space_id); + + if (rank != 0) + { + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + if (H5Dread (data_hid, H5T_NATIVE_UCHAR, H5S_ALL, H5S_ALL, + H5P_DEFAULT, (void *) &mord) < 0) + { + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + H5Dclose (data_hid); +#if HAVE_HDF5_18 + data_hid = H5Dopen (group_hid, "prim", H5P_DEFAULT); +#else + data_hid = H5Dopen (group_hid, "prim"); +#endif + space_id = H5Dget_space (data_hid); + rank = H5Sget_simple_extent_ndims (space_id); + + if (rank != 0) + { + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + if (H5Dread (data_hid, H5T_NATIVE_UINT, H5S_ALL, H5S_ALL, + H5P_DEFAULT, (void *) &prim) < 0) + { + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + H5Dclose (data_hid); +#if HAVE_HDF5_18 + data_hid = H5Dopen (group_hid, "val", H5P_DEFAULT); +#else + data_hid = H5Dopen (group_hid, "val"); +#endif + space_id = H5Dget_space (data_hid); + rank = H5Sget_simple_extent_ndims (space_id); + + // Only handle matrices for now + if (rank != 2) + { + H5Sclose (space_id); + H5Dclose (data_hid); + H5Gclose (group_hid); + return false; + } + + OCTAVE_LOCAL_BUFFER (hsize_t, hdims, rank); + OCTAVE_LOCAL_BUFFER (hsize_t, maxdims, rank); + + H5Sget_simple_extent_dims (space_id, hdims, maxdims); + MArray m (dim_vector (hdims[1], hdims[0])); + + int *re = m.fortran_vec (); + if (H5Dread (data_hid, H5T_NATIVE_UINT, H5S_ALL, H5S_ALL, + H5P_DEFAULT, (void *) re) >= 0) + { + retval = true; + gval = galois (m, mord, prim); + } + + H5Sclose (space_id); + H5Dclose (data_hid); + +#elif defined (HAVE_OCTAVE_BASE_VALUE_GRIPE_LOAD_SAVE) + gripe_load ("hdf5"); +#else + warning ("galois: loading hdf5 files not available"); +#endif + + return retval; +} + +/* + ;;; Local Variables: *** + ;;; mode: C++ *** + ;;; End: *** +*/ diff --git a/src/ov-galois.h b/src/ov-galois.h new file mode 100644 index 0000000..95e6e66 --- /dev/null +++ b/src/ov-galois.h @@ -0,0 +1,186 @@ +//Copyright (C) 2003 David Bateman +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of the +// License, or (at your option) any later version. +// +// This program 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 +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, see +// . +// +// In addition to the terms of the GPL, you are permitted to link this +// program with any Open Source program, as defined by the Open Source +// Initiative (www.opensource.org) + +#if !defined (octave_galois_h) +#define octave_galois_h 1 + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include + +#include "galois.h" + +// The keys of the values in the octave map +#define __GALOIS_PRIMPOLY_STR "prim_poly" +#define __GALOIS_ORDER_STR "m" +#define __GALOIS_DATA_STR "x" +#ifdef GALOIS_DISP_PRIVATES +#define __GALOIS_LENGTH_STR "n" +#define __GALOIS_ALPHA_TO_STR "alpha_to" +#define __GALOIS_INDEX_OF_STR "index_of" +#endif + +#if !defined (HAVE_OCTAVE_HDF5_ID_TYPE) +#if defined (HAVE_HDF5) +typedef hid_t octave_hdf5_id; +#else +typedef int octave_hdf5_id; +#endif +#endif + +#if ! defined (OV_REP_TYPE) +# define OV_REP_TYPE octave_base_value +#endif + +//class octave_value_list; +//class tree_walker; + +// Data structures. + +class +octave_galois : public octave_base_value +{ +public: + + octave_galois (const Matrix& data = Matrix (0, 0), const int _m = 1, + const int _primpoly = 0) + { gval = galois (data, _m, _primpoly); } + + octave_galois (const galois& gm) + : octave_base_value (), gval (gm) { } + octave_galois (const octave_galois& s) + : octave_base_value (), gval (s.gval) { } + + ~octave_galois (void) { }; + + OV_REP_TYPE *clone (void) const { return new octave_galois (*this); } + OV_REP_TYPE *empty_clone (void) const { return new octave_galois (); } + + octave_value subsref (const std::string &type, + const std::list& idx); + + octave_value_list subsref (const std::string& type, + const std::list& idx, int) + { return subsref (type, idx); } + + octave_value do_index_op (const octave_value_list& idx, + bool resize_ok); + + octave_value do_index_op (const octave_value_list& idx) + { return do_index_op (idx, 0); } + + void assign (const octave_value_list& idx, const galois& rhs); + + dim_vector dims (void) const { return gval.dims (); } + + octave_value resize (const dim_vector& dv, bool) const; + + size_t byte_size (void) const { return gval.byte_size (); } + + octave_value all (int dim = 0) const { return gval.all (dim); } + octave_value any (int dim = 0) const { return gval.any (dim); } + + bool is_matrix_type (void) const { return true; } + + bool is_defined (void) const { return true; } + + bool OV_ISNUMERIC (void) const { return true; } + + bool is_constant (void) const { return true; } + + bool is_true (void) const; + + bool is_galois_type (void) const { return true; } + + bool print_as_scalar (void) const; + +#if defined (HAVE_OCTAVE_BASE_VALUE_PRINT_CONST) + void print (std::ostream& os, bool pr_as_read_syntax = false) const; +#else + void print (std::ostream& os, bool pr_as_read_syntax = false); +#endif + + void print_raw (std::ostream& os, bool pr_as_read_syntax = false) const; + + bool print_name_tag (std::ostream& os, const std::string& name) const; + + void print_info (std::ostream& os, const std::string& prefix) const; + + bool is_real_matrix (void) const { return false; } + + bool OV_ISREAL (void) const { return false; } + + // FIXME + bool valid_as_scalar_index (void) const { return false; } + + double double_value (bool = false) const; + + double scalar_value (bool frc_str_conv = false) const + { return double_value (frc_str_conv); } + + Matrix matrix_value (bool = false) const; + + NDArray array_value (bool = false) const; + + Complex complex_value (bool = false) const; + + ComplexMatrix complex_matrix_value (bool = false) const + { return ComplexMatrix ( matrix_value ()); } + + galois galois_value (void) const { return gval; } + + octave_value_list dotref (const octave_value_list& idx); + + int m (void) const { return gval.m (); } + int primpoly (void) const { return gval.primpoly (); } + + bool save_ascii (std::ostream& os); + + bool load_ascii (std::istream& is); + + bool save_binary (std::ostream& os, bool& save_as_floats); + + bool load_binary (std::istream& is, bool swap, + OCTAVE_MACH_INFO_FLOAT_FORMAT fmt); + + bool save_hdf5 (octave_hdf5_id loc_id, const char *name, bool save_as_floats); + + bool load_hdf5 (octave_hdf5_id loc_id, const char *name); + +private: + // The array used to managed the Galios Field data + galois gval; + +#if defined (DECLARE_OCTAVE_ALLOCATOR) + DECLARE_OCTAVE_ALLOCATOR +#endif + + DECLARE_OV_TYPEID_FUNCTIONS_AND_DATA +}; + +#endif + +/* +;;; Local Variables: *** +;;; mode: C++ *** +;;; End: *** +*/ diff --git a/src/primpoly.cc b/src/primpoly.cc new file mode 100644 index 0000000..49ea925 --- /dev/null +++ b/src/primpoly.cc @@ -0,0 +1,310 @@ +//Copyright (C) 2003 David Bateman +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of the +// License, or (at your option) any later version. +// +// This program 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 +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, see +// . +// +// In addition to the terms of the GPL, you are permitted to link this +// program with any Open Source program, as defined by the Open Source +// Initiative (www.opensource.org) + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include + +enum primpoly_type +{ + PRIMPOLY_MIN=0, + PRIMPOLY_MAX, + PRIMPOLY_ALL, + PRIMPOLY_K +}; + +static bool +do_isprimitive (const int& a, const int& m) +{ + // Fast return since primitive polynomial can't be even + if (!(a & 1)) + return false; + + RowVector repr (1< 3) + { + print_usage (); + return retval; + } + + m = args(0).int_value (); + + // The upper limit is an artifical limit caused by memory requirements + // in do_is_primitive. m=22 uses an array of 32MBytes!! + if ((m < 1) || (m > 22)) + { + error ("primpoly: m must be greater than 1 and less than 22"); + return retval; + } + if (nargin > 1) + { + if (args(1).is_scalar_type ()) + { + k = args(1).int_value (); + type = PRIMPOLY_K; + } + else if (args(1).is_string ()) + { + std::string s_arg = args(1).string_value (); + + if (s_arg == "nodisplay") + disp = false; + else if (s_arg == "min") + type = PRIMPOLY_MIN; + else if (s_arg == "max") + type = PRIMPOLY_MAX; + else if (s_arg == "all") + type = PRIMPOLY_ALL; + else { + error ("primpoly: invalid argument"); + return retval; + } + } + else + { + error ("primpoly: incorrect argument type"); + return retval; + } + } + + if (nargin > 2) + { + if (args(2).is_scalar_type ()) + { + if (type == PRIMPOLY_K) { + error ("primpoly: invalid arguments"); + return retval; + } + k = args(2).int_value (); + type = PRIMPOLY_K; + } + else if (args(2).is_string ()) + { + std::string s_arg = args(2).string_value (); + + if (s_arg == "nodisplay") { + if (!disp) { + error ("primpoly: invalid arguments"); + return retval; + } + disp = false; + } else if (!disp) { + if (s_arg == "min") + type = PRIMPOLY_MIN; + else if (s_arg == "max") + type = PRIMPOLY_MAX; + else if (s_arg == "all") + type = PRIMPOLY_ALL; + else { + error ("primpoly: invalid argument"); + return retval; + } + } else { + error ("primpoly: invalid arguments"); + return retval; + } + } + else + { + error ("primpoly: incorrect argument type"); + return retval; + } + } + + switch (type) + { + case PRIMPOLY_MIN: + primpolys.resize (1); + for (int i = (1< (1<. +// +// In addition to the terms of the GPL, you are permitted to link this +// program with any Open Source program, as defined by the Open Source +// Initiative (www.opensource.org) + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#ifndef SIZEOF_INT + #define SIZEOF_INT int(sizeof(int)) +#endif + +#define COL_MAJ(N) (N / (sizeof (int) << 3)) +#define COL_MIN(N) (N % (sizeof (int) << 3)) + +Array +get_errs (const int& nmin, const int& nmax, const int &nerrs) +{ + Array pos; + int cols = COL_MAJ (nmax)+1; + + OCTAVE_QUIT; + if (nerrs == 1) + { + pos.resize (dim_vector (nmax-nmin, cols), 0); + for (int i = nmin; i < nmax; i++) + { + pos(i-nmin, COL_MAJ (i)) = (1< new_pos = get_errs (i+1, nmax, nerrs-1); + int l = pos.rows (); + pos.resize (dim_vector (l+new_pos.rows (), cols), 0); + for (int j=0; j (int)(sizeof (int) << 3)) + { + error ("syndtable: codeword minus message length must be less than %d", + (int)(sizeof (int) << 3)); + return retval; + } + + // Check that the data in h is valid in GF(2) + for (int i = 0; i < m; i++) + for (int j = 0; j < n; j++) + if (((h(i, j) != 0) && (h(i, j) != 1)) || + ((h(i, j) - (double)((int)h(i, j))) != 0)) + { + error ("syndtable: parity check matrix contains invalid data"); + return retval; + } + + RowVector filled (nrows, 0); + Matrix table (nrows, n, 0); + unsigned int nfilled = nrows; + int nerrs = 1; + + // The first row of the table is for no errors + nfilled--; + filled(0) = 1; + + while (nfilled != 0) + { + // Get all possible combinations of nerrs bit errors in n bits + Array errpos = get_errs (0, n, nerrs); + + // Calculate the syndrome with the error vectors just calculated + for (int j = 0; j < errpos.rows (); j++) + { + int syndrome = 0; + for (int i = 0; i < m; i++) + { + for (int k = 0; k < n; k++) + syndrome ^= (errpos(j, COL_MAJ (k)) & + ((unsigned int)h(i, k) << COL_MIN (k)) ? + ((unsigned int)1<<(m-i-1)) : 0); + } + + // Now use the syndrome as the rows indices to put the error vectors + // in place + if (((unsigned int)syndrome < nrows) && !filled(syndrome)) + { + filled(syndrome) = 1; + nfilled--; + for (int i = 0; i < n; i++) + table(syndrome, i) = ((errpos(j, COL_MAJ (i)) & + ((unsigned int)1 << COL_MIN (i))) != 0); + } + } + + nerrs++; + } + + retval = octave_value (table); + return retval; +} + +/* +%% Test input validation +%!error syndtable () +%!error syndtable (1, 2) +%!error syndtable ([1 2]) +*/ diff --git a/src/undef-ah-octave.h b/src/undef-ah-octave.h new file mode 100644 index 0000000..efad7b5 --- /dev/null +++ b/src/undef-ah-octave.h @@ -0,0 +1,27 @@ +/* To be included at the top of config.h (by autoheader). Avoid + warnings for redefining AH-generated preprocessor symbols of + Octave. */ + +#ifdef PACKAGE_BUGREPORT +#undef PACKAGE_BUGREPORT +#endif + +#ifdef PACKAGE_NAME +#undef PACKAGE_NAME +#endif + +#ifdef PACKAGE_STRING +#undef PACKAGE_STRING +#endif + +#ifdef PACKAGE_TARNAME +#undef PACKAGE_TARNAME +#endif + +#ifdef PACKAGE_URL +#undef PACKAGE_URL +#endif + +#ifdef PACKAGE_VERSION +#undef PACKAGE_VERSION +#endif -- cgit v1.2.3 From c0a2207d2c063deb9d9836b04acfc506abc4bb73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Laboissi=C3=A8re?= Date: Sun, 15 Aug 2021 15:50:43 -0300 Subject: Import octave-communications_1.2.3-2.debian.tar.xz [dgit import tarball octave-communications 1.2.3-2 octave-communications_1.2.3-2.debian.tar.xz] --- changelog | 379 ++++++++++++++++++++++++++++++++++ clean | 14 ++ control | 54 +++++ copyright | 65 ++++++ gbp.conf | 4 + octave-communications-common.doc-base | 8 + octave-communications-common.docs | 1 + octave-communications-common.info | 1 + patches/depends-on-statistics.patch | 21 ++ patches/info-dir-section.patch | 20 ++ patches/random-seed-for-pdf-doc.patch | 48 +++++ patches/series | 3 + rules | 30 +++ source/format | 1 + source/options | 1 + upstream/metadata | 3 + watch | 2 + 17 files changed, 655 insertions(+) create mode 100644 changelog create mode 100644 clean create mode 100644 control create mode 100644 copyright create mode 100644 gbp.conf create mode 100644 octave-communications-common.doc-base create mode 100644 octave-communications-common.docs create mode 100644 octave-communications-common.info create mode 100644 patches/depends-on-statistics.patch create mode 100644 patches/info-dir-section.patch create mode 100644 patches/random-seed-for-pdf-doc.patch create mode 100644 patches/series create mode 100755 rules create mode 100644 source/format create mode 100644 source/options create mode 100644 upstream/metadata create mode 100644 watch diff --git a/changelog b/changelog new file mode 100644 index 0000000..56d4c53 --- /dev/null +++ b/changelog @@ -0,0 +1,379 @@ +octave-communications (1.2.3-2) unstable; urgency=medium + + * Upload to unstable + * d/rules: Use target execute_after_dh_auto_install instead of + override_dh_auto_install + + -- Rafael Laboissière Sun, 15 Aug 2021 15:50:43 -0300 + +octave-communications (1.2.3-1) experimental; urgency=medium + + * New upstream version 1.2.3 + * d/clean: Remove files src/*.cc-tst + * d/copyright: Reflect upstream changes + * d/control: Set "Multi-Arch: foreign" for package + octave-communications-common + + -- Rafael Laboissière Sat, 17 Apr 2021 08:53:34 -0300 + +octave-communications (1.2.2-4) unstable; urgency=medium + + * Team upload + * Add epstool to Build-Depends (Closes: #977013) + * Bump S-V to 4.5.1 + + -- Sébastien Villemot Thu, 10 Dec 2020 10:42:14 +0100 + +octave-communications (1.2.2-3) unstable; urgency=medium + + [ Debian Janitor ] + * Apply multi-arch hints. + + octave-communications: Add Multi-Arch: same. + + [ Rafael Laboissière ] + * d/p/info-dir-section.patch: Set Forwarded not-needed + + -- Rafael Laboissière Tue, 10 Nov 2020 18:35:34 -0300 + +octave-communications (1.2.2-2) unstable; urgency=medium + + [ Rafael Laboissière ] + * d/control: Bump Standards-Version to 4.5.0 (no changes needed) + * d/u/metadata: New file + * d/control: Bump debhelper compatibitlity level to 13 + * d/u/metadata: Drop Name and Contact fields + + [ Debian Janitor ] + * Fix day-of-week for changelog entry 1.0.5-1. + + -- Rafael Laboissière Tue, 14 Jul 2020 06:52:43 -0300 + +octave-communications (1.2.2-1) unstable; urgency=medium + + * New upstream version 1.2.2 + * d/p/octave-4.4.patch: Drop patch (applied upstream) + * d/p/depends-on-statistics.patch: Refresh for new upstream version + * d/copyright: Reflect upstream changes + * d/control: Add pkg-config to the list of build-dependencies + * d/clean: + + Avoid deletion of file src/config.h.in + + Delete file src/oct-alt-includes.h + + -- Rafael Laboissière Tue, 07 Jan 2020 03:23:51 -0300 + +octave-communications (1.2.1-9) unstable; urgency=medium + + * d/control: Bump dependency on dh-octave to >= 0.7.1 + + -- Rafael Laboissiere Sat, 02 Nov 2019 12:29:41 -0300 + +octave-communications (1.2.1-8) unstable; urgency=medium + + * d/control: + + Bump Standards-Version to 4.4.1 (no changes needed) + + Bump dependency on dh-octave to >= 0.7.0. + This allows the injection of the virtual package octave-abi-N + into the package's list of dependencies. + + -- Rafael Laboissiere Fri, 01 Nov 2019 05:56:49 -0300 + +octave-communications (1.2.1-7) unstable; urgency=medium + + * d/control: + + Add Rules-Requires-Root: no + + Bump Standards-Version to 4.3.0 + + Build depend on texlive-plain-generic + + Bump to debhelper compat level 12 + * Build-depend on debhelper-compat instead of using d/compat + + -- Rafael Laboissiere Wed, 02 Jan 2019 22:54:13 -0200 + +octave-communications (1.2.1-6) unstable; urgency=medium + + * Team upload + + [ Mike Miller ] + * d/control, d/copyright: Use secure URL for upstream source. + + [ Rafael Laboissiere ] + * d/control: Bump Standards-Version to 4.1.4 (no changes needed) + + [ Sébastien Villemot ] + * octave-4.2.patch renamed to octave-4.4.patch, with more fixes for 4.4 + * Add dependency on octave-statistics + qfuncinv() uses norminv(). This function is no longer in Octave core + since 4.4, and has moved to the statistics package. + + depends-on-statistics.patch: new patch + + d/control: add B-D on octave-statistics + + -- Sébastien Villemot Wed, 20 Jun 2018 11:22:43 +0200 + +octave-communications (1.2.1-5) unstable; urgency=medium + + * Use dh-octave for building the package + * d/control: + + Use Debian's GitLab URLs in Vcs-* headers + + Change Maintainer to team+pkg-octave-team@tracker.debian.org + + -- Rafael Laboissiere Sat, 10 Feb 2018 07:27:16 -0200 + +octave-communications (1.2.1-4) unstable; urgency=medium + + * Use the dh-based version of octave-pkg-dev + * Set debhelper compatibility level to >= 11 + * d/control: + + Add Testsuite field + + Build-depend on gnuplot-nox, instead of gnuplot + + Bump Standards-Version to 4.1.3 (no changes needed) + + -- Rafael Laboissiere Fri, 29 Dec 2017 22:13:13 -0200 + +octave-communications (1.2.1-3) unstable; urgency=medium + + * Team upload. + + [ Sébastien Villemot ] + * d/p/octave-4.2.patch: new patch, fixes FTBFS against Octave 4.2. + (Closes: #867014) + * d/copyright: use secure URL for format. + * Bump to debhelper compat level 10. + * d/watch: bump to format version 4. + * d/rules: add support for "nodoc" flag of DEB_BUILD_OPTIONS. + * d/control: + + Drop unneeded versioned dependencies. + + Bump to Standards-Version 4.0.0. + + [ Rafael Laboissiere ] + * d/control: Use cgit instead of gitweb in Vcs-Browser URL + + -- Sébastien Villemot Mon, 03 Jul 2017 15:41:37 +0200 + +octave-communications (1.2.1-2) unstable; urgency=medium + + * d/control: Use secure URIs in the Vcs-* fields + * d/control: Bump Standards-Version to 3.9.8 (no changes needed) + * Reproducible build + + d/rules: Set SOURCE_DATE_EPOCH envvar, for + + d/p/random-seed-for-pdf-doc.patch: New patch + + d/rules: Avoid non-deterministic tempfile names in PDF files + * Clean files explicitly + + d/rules: Drop the clean target + + d/clean: Add file + + -- Rafael Laboissiere Thu, 28 Jul 2016 18:25:02 -0300 + +octave-communications (1.2.1-1) unstable; urgency=medium + + * Team upload. + + [ Rafael Laboissiere ] + * Imported Upstream version 1.2.1 + * d/p/autoload-yes.patch: Remove patch (deprecated upstream) + * d/control: Bump Standards-Version to 3.9.6 (no changes needed) + + [ Sébastien Villemot ] + * d/p/hdf5-ldflags.patch: drop patch, no longer needed. + + -- Sébastien Villemot Mon, 20 Jul 2015 10:22:27 +0200 + +octave-communications (1.2.0-2) unstable; urgency=medium + + * Team upload. + * Uploaders: set as Rafael Laboissiere and Mike Miller. + * hdf5-ldflags.patch: new patch, inject HDF5 LDFLAGS in the build. + Needed for the new HDF5 1.8.13 layout. (Closes: #758733) + + -- Sébastien Villemot Thu, 21 Aug 2014 22:10:44 +0200 + +octave-communications (1.2.0-1) unstable; urgency=low + + * Imported Upstream version 1.2.0 + * Bump to Standards-Version 3.9.5, no changes needed + * Dropped patches (applied upstream): + - oct2dec.patch + - build-documentation.patch + - avoid-makeinfo-section-raising-error.patch + * Refreshed patches + * Update copyright information + + -- Thomas Weber Mon, 02 Dec 2013 00:03:59 +0100 + +octave-communications (1.1.1-2) unstable; urgency=low + + [ Rafael Laboissiere ] + * avoid-makeinfo-section-raising-error.patch: new patch, fixes FTBFS + * Remove obsolete DM-Upload-Allowed flag + * Bump to Standards-Version 3.9.4, no changes needed + * debian/copyright: Use octave-maintainers mailing list as upstream contact + + [ Thomas Weber ] + * debian/control: Use canonical URLs in Vcs-* fields + + [ Sébastien Villemot ] + * Use my @debian.org email address + + -- Sébastien Villemot Wed, 12 Jun 2013 10:41:31 +0200 + +octave-communications (1.1.1-1) unstable; urgency=low + + [ Sébastien Villemot ] + * Imported Upstream version 1.1.1 + * LU-class-name-clash.patch: remove patch, applied upstream + * fix-huffmandict-test.patch: remove patch, applied upstream + * autoload-yes.patch: new patch + * oct2dec.patch: new patch + * Build-Depends on octave-signal + * debian/copyright: reflect upstream changes + * debian/rules: remove obsolete hack for wrong permission in upstream tarball + * Replace versioned Conflicts by Breaks+Replaces to make lintian happy + * Add lintian overrides for false positives on hardening build flags + + [ Rafael Laboissiere ] + * debian/watch: Use the SourceForge redirector + + -- Sébastien Villemot Mon, 21 May 2012 09:01:30 +0200 + +octave-communications (1.1.0-2) unstable; urgency=low + + * Add missing build-dependency on ghostscript + + -- Sébastien Villemot Tue, 20 Mar 2012 21:34:21 +0100 + +octave-communications (1.1.0-1) unstable; urgency=low + + [ Rafael Laboissiere ] + * Imported Upstream version 1.1.0 + * Bump to debhelper compat level 9 + * Build-depend on octave-pkg-dev >= 1.0.0, to build against Octave 3.6 + * Bump to Standards-Version 3.9.3, no changes needed + * Add Sébastien Villemot to the list of Uploaders + * Add patch for avoiding name clash with LU class (taken from upstream SVN) + * Add patch for fixing the test of huffmandict (taken from upstream SVN) + * Add patch for setting the direntry of the info documentation + * Build and install the PDF and info forms of documentation + * Drop the build-dependency on octave-signal + * debian/copyright: update to machine-readable format 1.0 + + -- Thomas Weber Mon, 19 Mar 2012 18:01:05 +0100 + +octave-communications (1.0.10-3) unstable; urgency=low + + * debian/control: + - Remove Rafael Laboissiere from Uploaders (Closes: #571842) + - Remove Ólafur Jens Sigurðsson from Uploaders + * Fix homepage URL (closes: #600480) + * Switch to dpkg-source 3.0 (quilt) format + * Don't include the -1 revision in the dependency on octave-signal + introduced in 1.0.10-1; this makes Lintian happy. + * Bump Standards-Version to 3.9.1, no changes needed. + + -- Thomas Weber Mon, 21 Feb 2011 22:22:11 +0100 + +octave-communications (1.0.10-2) unstable; urgency=low + + * Build against hdf5 (1.8.4) (closes: #570020) + + -- Thomas Weber Thu, 18 Feb 2010 23:40:36 +0100 + +octave-communications (1.0.10-1) unstable; urgency=low + + [ Rafael Laboissiere ] + * debian/control: Build-depend on octave-pkg-dev >= 0.7.0, such that the + package is built against octave3.2 + + [ Thomas Weber ] + * New upstream release + * Bump dependency on octave-signal to (>= 1.0.10-1), to get the version for + Octave 3.2 + * Remove patch: call-mlock-with-arg.diff, it was only necessary for + octave3.0 + * debian/rules: Drop code for changing permissions of files (applied + upstream) + * debian/control: Fix typo + * Install PDF documentation via octave-communications-common.docs and remove + the code for deleting unnecessary files from debian/rules. + + -- Thomas Weber Sun, 15 Nov 2009 17:02:27 +0100 + +octave-communications (1.0.9-2) unstable; urgency=low + + * debian/rules (install/octave-communications): Do the transfer of files + for the -common package in this rule, otherwise the arch-independent + files end up in the wrong place for binary-only builds + * debian/control: Make octave-communications-common conflict with + versions of octave-communications strictly inferior to 1.0.9-1 + + -- Rafael Laboissiere Sat, 06 Jun 2009 18:10:56 +0200 + +octave-communications (1.0.9-1) unstable; urgency=low + + * New upstream release + * Put the architecture independent files *.m into the separate + octave-communications-common package. This is required by Policy. + * debian/patches/call-mlock-with-arg.diff: Add patch for making the + package compile against Octave 3.0.5 + * debian/rules: + + Include patchsys-quilt.mk + + Fix permission of some installed *.m scripts + + Remove unneeded documentation sources from /usr/share/doc + * debian/control: + + (Build-Depends): Add quilt + + (Standards-Version): Bump to 3.8.1 (no changes needed) + + (Depends): Add ${misc:Depends} + + (Vcs-Git, Vcs-Browser): Adjust to new Git repository + * debian/copyright: + + Use DEP5 URL in Format-Specification + + Use separate License stanzas for instructing about the location of + the different licenses used in the package + * debian/README.source: Add file explaining the quilt patch system, as + required by the Policy + + -- Rafael Laboissiere Sun, 24 May 2009 11:40:07 +0200 + +octave-communications (1.0.8-2) unstable; urgency=low + + [ Rafael Laboissiere ] + * debian/copyright: Add header + * debian/control: Bump build-dependency on octave-pkg-dev to >= 0.6.4, + such that the package is built with the versioned packages directory + + [ Thomas Weber ] + * Upload to unstable + + -- Thomas Weber Sun, 29 Mar 2009 00:05:09 +0100 + +octave-communications (1.0.8-1) experimental; urgency=low + + [ Rafael Laboissiere ] + * debian/rules: Use debian/clean instead of manually cleaning files + * debian/compat, debian/control: Bump build-dependency on debhelper to + >= 7.0.0, otherwise debian/clean is moot + * debian/clean: New file + * debian/control: Bump Standards-Version to 3.8.0 (no changes needed) + + [ Thomas Weber ] + * New upstream release + * debian/control: + - Add octave-signal to build-depends, it's needed for some tests + - Bump dependency on octave-pkg-dev to 0.6.1, to get the experimental + version + + -- Thomas Weber Sun, 30 Nov 2008 21:14:49 +0100 + +octave-communications (1.0.6-1) unstable; urgency=low + + [ Ólafur Jens Sigurðsson ] + * New upstream version. + + [ Rafael Laboissiere ] + * The source files comms.texi and comms.txi of the PDF documentation + distributed with the package are now included in the upstream tarball. + This makes the package DFSG-compliant (really, closes: #468497) + + -- Rafael Laboissiere Sat, 10 May 2008 11:49:10 +0000 + +octave-communications (1.0.5-1) unstable; urgency=low + + * Initial release (closes: #468497) + + -- Ólafur Jens Sigurðsson Wed, 14 Nov 2007 23:54:34 +0100 diff --git a/clean b/clean new file mode 100644 index 0000000..b4b63f5 --- /dev/null +++ b/clean @@ -0,0 +1,14 @@ +doc/*.pdf +doc/*.dvi +doc/*.info +doc/*.texi +doc/*.eps +doc/DOCSTRINGS +src/Makefile +src/config.h +src/config.log +src/config.status +src/*.o +src/*.oct +src/oct-alt-includes.h +src/*.cc-tst diff --git a/control b/control new file mode 100644 index 0000000..f6e4b58 --- /dev/null +++ b/control @@ -0,0 +1,54 @@ +Source: octave-communications +Maintainer: Debian Octave Group +Uploaders: Rafael Laboissière , + Mike Miller +Section: math +Priority: optional +Build-Depends: debhelper-compat (= 13), + dh-octave (>= 0.7.1), + ghostscript, + gnuplot-nox, + octave-signal, + octave-statistics, + pkg-config, + texlive, + texlive-plain-generic, + epstool +Standards-Version: 4.5.1 +Vcs-Browser: https://salsa.debian.org/pkg-octave-team/octave-communications +Vcs-Git: https://salsa.debian.org/pkg-octave-team/octave-communications.git +Homepage: https://octave.sourceforge.io/communications/ +Testsuite: autopkgtest-pkg-octave +Rules-Requires-Root: no + +Package: octave-communications +Architecture: any +Depends: ${misc:Depends}, + ${shlibs:Depends}, + octave-communications-common (= ${source:Version}) +Multi-Arch: same +Description: communications package for Octave + This package provides functions for Octave, a numerical computation + software, to perform error analysis on communication signals, + convert between analog and digital signals, and many more functions + pertaining to signal analysis. + . + This Octave add-on package is part of the Octave-Forge project. + +Package: octave-communications-common +Architecture: all +Depends: ${misc:Depends}, + ${octave:Depends} +Breaks: octave-communications (<< 1.0.9-1) +Replaces: octave-communications (<< 1.0.9-1) +Multi-Arch: foreign +Description: communications package for Octave (arch-indep files) + This package provides functions for Octave, a numerical computation + software, to perform error analysis on communication signals, + convert between analog and digital signals, and many more functions + pertaining to signal analysis. + . + This Octave add-on package is part of the Octave-Forge project. + . + This package contains the architecture-independent files for the + octave-communications package. diff --git a/copyright b/copyright new file mode 100644 index 0000000..e924922 --- /dev/null +++ b/copyright @@ -0,0 +1,65 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: Communications package for Octave +Upstream-Contact: The Octave Community +Source: https://octave.sourceforge.io/communications/ + +Files: * +Copyright: 2002-2003, 2011 David Bateman + 2006-2007, 2011 Muthiah Annamalai + 2007-2008 Sylvain Pelissier + 2006 Charalampos C. Tsimenidis + 2001 Laurent Mazet + 2010 Mark Borgerding + 2000-2001 Paul Kienzle + 2007 Gorka Lertxundi + 1994-1997 Robert Morelos-Zaragoza + 2002 Phil Karn + 2009 Christian Neumair + 2011 Ferran Mesas Garcia + 2012 Tony Richardson + 2012 Mike Miller + 2019 Nir Krakauer + 2020 Pedro Rodriguez Torija + 2020 Nicholas Jankowski + 2021 The Octave Project Developers +License: GPL-3+ + +Files: doc/comms.txi +Copyright: 2003 David Bateman, Laurent Mazet, Paul Kienzle, Mike Miller +License: other + Permission is granted to make and distribute verbatim copies of + this manual provided the copyright notice and this permission notice + are preserved on all copies. + . + Permission is granted to copy and distribute modified versions of this + manual under the conditions for verbatim copying, provided that the entire + resulting derived work is distributed under the terms of a permission + notice identical to this one. + . + Permission is granted to copy and distribute translations of this manual + into another language, under the same conditions as for modified versions. + +Files: debian/* +Copyright: 2008 Ólafur Jens Sigurðsson + 2008-2011 Thomas Weber + 2008, 2009, 2012, 2019-2021 Rafael Laboissiere + 2012 Sébastien Villemot +License: GPL-3+ + +License: GPL-3+ + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + . + This program 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 General Public License for more details. + . + You should have received a copy of the GNU General Public License along + with this program. If not, see . + . + On Debian systems, the complete text of the GNU General Public + License, version 3, can be found in the file + `/usr/share/common-licenses/GPL-3'. diff --git a/gbp.conf b/gbp.conf new file mode 100644 index 0000000..6b65fe0 --- /dev/null +++ b/gbp.conf @@ -0,0 +1,4 @@ +[DEFAULT] +debian-branch = debian/latest +upstream-branch = upstream/latest +pristine-tar = True diff --git a/octave-communications-common.doc-base b/octave-communications-common.doc-base new file mode 100644 index 0000000..88fdeea --- /dev/null +++ b/octave-communications-common.doc-base @@ -0,0 +1,8 @@ +Document: octave-communications-manual +Title: Communications Toolbox for Octave +Author: David Bateman, Laurent Mazet, and Paul Kienzle +Abstract: Documentation for the Communications Package for GNU Octave +Section: Science/Mathematics + +Format: PDF +Files: /usr/share/doc/octave-communications-common/comms.pdf.gz diff --git a/octave-communications-common.docs b/octave-communications-common.docs new file mode 100644 index 0000000..5add8d8 --- /dev/null +++ b/octave-communications-common.docs @@ -0,0 +1 @@ +doc/comms.pdf diff --git a/octave-communications-common.info b/octave-communications-common.info new file mode 100644 index 0000000..21537fe --- /dev/null +++ b/octave-communications-common.info @@ -0,0 +1 @@ +doc/comms.info diff --git a/patches/depends-on-statistics.patch b/patches/depends-on-statistics.patch new file mode 100644 index 0000000..9a99617 --- /dev/null +++ b/patches/depends-on-statistics.patch @@ -0,0 +1,21 @@ +Description: communication now depends on the statistics package + qfuncinv() uses norminv(). + This function is no longer in Octave core since 4.4, and has moved to + the statistics package. +Author: Sébastien Villemot +Bug: https://savannah.gnu.org/bugs/index.php?54156 +Reviewed-by: Rafael Laboissière +Last-Update: 2020-01-06 +--- +This patch header follows DEP-3: http://dep.debian.net/deps/dep3/ +--- a/DESCRIPTION ++++ b/DESCRIPTION +@@ -5,7 +5,7 @@ Author: various authors + Maintainer: Nir Krakauer + Title: Communications + Description: Digital Communications, Error Correcting Codes (Channel Code), Source Code functions, Modulation and Galois Fields +-Depends: octave (>= 4.4), signal (>= 1.1.3) ++Depends: octave (>= 4.4), signal (>= 1.1.3), statistics + Autoload: no + License: GPLv3+ + Url: http://octave.sf.net diff --git a/patches/info-dir-section.patch b/patches/info-dir-section.patch new file mode 100644 index 0000000..c7f7420 --- /dev/null +++ b/patches/info-dir-section.patch @@ -0,0 +1,20 @@ +Description: Add category directory entry for the info documentation + This is a requirement in Debian. +Author: Rafael Laboissiere +Forwarded: not-needed +Last-Update: 2012-03-12 + +--- a/doc/comms.txi ++++ b/doc/comms.txi +@@ -28,6 +28,11 @@ + into another language, under the same conditions as for modified versions. + @end titlepage + ++@dircategory Math ++@direntry ++* Communications: (comms). Communications Toolbox for Octave ++@end direntry ++ + @contents + + @ifnottex diff --git a/patches/random-seed-for-pdf-doc.patch b/patches/random-seed-for-pdf-doc.patch new file mode 100644 index 0000000..3c9fe04 --- /dev/null +++ b/patches/random-seed-for-pdf-doc.patch @@ -0,0 +1,48 @@ +Description: Add seed for random number generators + This patch add seeds for the random number generators used when + building the PDF figures of the manual. This ensures that the data + appearing in the figures is reproducible. +Author: Rafael Laboissière +Forwarded: https://savannah.gnu.org/bugs/index.php?48655 +Last-Update: 2016-07-28 + +--- octave-communications-1.2.1.orig/doc/commsimages.m ++++ octave-communications-1.2.1/doc/commsimages.m +@@ -28,10 +28,12 @@ function commsimages (nm, typ) + d_typ = ["-d", typ]; + endif + ++ seed = 1234; ++ + if (strcmp (nm, "awgn")) + x = 0:0.1:2*pi; + y = sin (x); +- noisy = awgn (y, 10, "measured"); ++ noisy = awgn (y, 10, "measured", [], seed); + plot (x, y, "r"); + hold on; + plot (x, noisy, "g--"); +@@ -42,9 +44,9 @@ function commsimages (nm, typ) + ovsp = 50; + x = 1:n; + xi = 1:1/ovsp:n-0.1; +- y = randsrc (1, n, [1 + 1i, 1 - 1i, -1 - 1i, -1 + 1i]); ++ y = randsrc (1, n, [1 + 1i, 1 - 1i, -1 - 1i, -1 + 1i], seed); + yi = interp1 (x, y, xi); +- noisy = awgn (yi, 15, "measured"); ++ noisy = awgn (yi, 15, "measured", [], seed); + cf = gcf (); + set (cf, "tag", "eyediagram"); + eyediagram (noisy, ovsp, [], [], [], cf); +@@ -54,9 +56,9 @@ function commsimages (nm, typ) + ovsp = 5; + x = 1:n; + xi = 1:1/ovsp:n-0.1; +- y = randsrc (1, n, [1 + 1i, 1 - 1i, -1 - 1i, -1 + 1i]); ++ y = randsrc (1, n, [1 + 1i, 1 - 1i, -1 - 1i, -1 + 1i], seed); + yi = interp1 (x, y, xi); +- noisy = awgn (yi, 15, "measured"); ++ noisy = awgn (yi, 15, "measured", [], seed); + cf = gcf (); + set (cf, "tag", "scatterplot"); + f = scatterplot (noisy, 1, 0, "b", cf); diff --git a/patches/series b/patches/series new file mode 100644 index 0000000..68b5f69 --- /dev/null +++ b/patches/series @@ -0,0 +1,3 @@ +info-dir-section.patch +random-seed-for-pdf-doc.patch +depends-on-statistics.patch diff --git a/rules b/rules new file mode 100755 index 0000000..1d478a1 --- /dev/null +++ b/rules @@ -0,0 +1,30 @@ +#!/usr/bin/make -f +# -*- makefile -*- + +include /usr/share/dpkg/pkg-info.mk +export SOURCE_DATE_EPOCH + +%: + dh $@ --buildsystem=octave --with=octave + + +pkg = communications +archshr = $(CURDIR)/debian/octave-$(pkg)/usr/share +indepshr = $(CURDIR)/debian/octave-$(pkg)-common/usr/share + +DEB_DH_INSTALL_SOURCEDIR = debian/octave-$(pkg) + +ifeq (,$(filter nodoc,$(DEB_BUILD_OPTIONS))) +override_dh_auto_build: + for i in awgn.pdf eyediagram.pdf scatterplot.pdf ; do \ + make -C doc $$i ; \ + sed -i -e 's|/tmp/oct-.......eps|/tmp/oct.eps|' doc/$$i ; \ + done + make -C doc comms.pdf comms.info +endif + +execute_after_dh_auto_install: + # Move the architecture independent files into the appropriate + # package + mkdir -p $(indepshr) + mv $(archshr)/octave $(indepshr) diff --git a/source/format b/source/format new file mode 100644 index 0000000..163aaf8 --- /dev/null +++ b/source/format @@ -0,0 +1 @@ +3.0 (quilt) diff --git a/source/options b/source/options new file mode 100644 index 0000000..9208e7b --- /dev/null +++ b/source/options @@ -0,0 +1 @@ +extend-diff-ignore=doc/comms\.info|doc/comms\.texi diff --git a/upstream/metadata b/upstream/metadata new file mode 100644 index 0000000..fcf16da --- /dev/null +++ b/upstream/metadata @@ -0,0 +1,3 @@ +Bug-Database: https://savannah.gnu.org/bugs/?group=octave +Bug-Submit: https://savannah.gnu.org/bugs/?func=additem&group=octave +Repository-Browse: https://octave.sourceforge.io/pkg-repository/communications/ diff --git a/watch b/watch new file mode 100644 index 0000000..bd665d0 --- /dev/null +++ b/watch @@ -0,0 +1,2 @@ +version=4 +http://sf.net/octave/communications-(.+)\.tar\.gz -- cgit v1.2.3 From ff1432dc0747980d87d5b67a17e2cf4339b6609c Mon Sep 17 00:00:00 2001 From: Rafael Laboissiere Date: Sun, 15 Aug 2021 15:50:43 -0300 Subject: Add category directory entry for the info documentation Forwarded: not-needed Last-Update: 2012-03-12 This is a requirement in Debian. Gbp-Pq: Name info-dir-section.patch --- doc/comms.txi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/comms.txi b/doc/comms.txi index 9088de9..c34b1b1 100644 --- a/doc/comms.txi +++ b/doc/comms.txi @@ -28,6 +28,11 @@ Permission is granted to copy and distribute translations of this manual into another language, under the same conditions as for modified versions. @end titlepage +@dircategory Math +@direntry +* Communications: (comms). Communications Toolbox for Octave +@end direntry + @contents @ifnottex -- cgit v1.2.3 From 6135d46c5e138e4dd66f8d820ac8850a0f404d7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Laboissi=C3=A8re?= Date: Sun, 15 Aug 2021 15:50:43 -0300 Subject: Add seed for random number generators Forwarded: https://savannah.gnu.org/bugs/index.php?48655 Last-Update: 2016-07-28 This patch add seeds for the random number generators used when building the PDF figures of the manual. This ensures that the data appearing in the figures is reproducible. Gbp-Pq: Name random-seed-for-pdf-doc.patch --- doc/commsimages.m | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/doc/commsimages.m b/doc/commsimages.m index 36eca98..83a239f 100644 --- a/doc/commsimages.m +++ b/doc/commsimages.m @@ -28,10 +28,12 @@ function commsimages (nm, typ) d_typ = ["-d", typ]; endif + seed = 1234; + if (strcmp (nm, "awgn")) x = 0:0.1:2*pi; y = sin (x); - noisy = awgn (y, 10, "measured"); + noisy = awgn (y, 10, "measured", [], seed); plot (x, y, "r"); hold on; plot (x, noisy, "g--"); @@ -42,9 +44,9 @@ function commsimages (nm, typ) ovsp = 50; x = 1:n; xi = 1:1/ovsp:n-0.1; - y = randsrc (1, n, [1 + 1i, 1 - 1i, -1 - 1i, -1 + 1i]); + y = randsrc (1, n, [1 + 1i, 1 - 1i, -1 - 1i, -1 + 1i], seed); yi = interp1 (x, y, xi); - noisy = awgn (yi, 15, "measured"); + noisy = awgn (yi, 15, "measured", [], seed); cf = gcf (); set (cf, "tag", "eyediagram"); eyediagram (noisy, ovsp, [], [], [], cf); @@ -54,9 +56,9 @@ function commsimages (nm, typ) ovsp = 5; x = 1:n; xi = 1:1/ovsp:n-0.1; - y = randsrc (1, n, [1 + 1i, 1 - 1i, -1 - 1i, -1 + 1i]); + y = randsrc (1, n, [1 + 1i, 1 - 1i, -1 - 1i, -1 + 1i], seed); yi = interp1 (x, y, xi); - noisy = awgn (yi, 15, "measured"); + noisy = awgn (yi, 15, "measured", [], seed); cf = gcf (); set (cf, "tag", "scatterplot"); f = scatterplot (noisy, 1, 0, "b", cf); -- cgit v1.2.3 From e7f2170ac33e39032c1ef54f1b393242218921cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Villemot?= Date: Sun, 15 Aug 2021 15:50:43 -0300 Subject: communication now depends on the statistics package MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bug: https://savannah.gnu.org/bugs/index.php?54156 Reviewed-by: Rafael Laboissière Last-Update: 2020-01-06 qfuncinv() uses norminv(). This function is no longer in Octave core since 4.4, and has moved to the statistics package. Last-Update: 2020-01-06 Gbp-Pq: Name depends-on-statistics.patch --- DESCRIPTION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/DESCRIPTION b/DESCRIPTION index dbb7b05..8fbcf15 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -5,7 +5,7 @@ Author: various authors Maintainer: Nir Krakauer Title: Communications Description: Digital Communications, Error Correcting Codes (Channel Code), Source Code functions, Modulation and Galois Fields -Depends: octave (>= 4.4), signal (>= 1.1.3) +Depends: octave (>= 4.4), signal (>= 1.1.3), statistics Autoload: no License: GPLv3+ Url: http://octave.sf.net -- cgit v1.2.3 From e5a2f3727ae9bdf6047920849625e4eb32eefa91 Mon Sep 17 00:00:00 2001 From: Rafael Laboissiere Date: Mon, 24 Jan 2022 01:31:44 -0300 Subject: Add category directory entry for the info documentation Forwarded: not-needed Last-Update: 2012-03-12 This is a requirement in Debian. Gbp-Pq: Name info-dir-section.patch --- doc/comms.txi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/comms.txi b/doc/comms.txi index 9088de9..c34b1b1 100644 --- a/doc/comms.txi +++ b/doc/comms.txi @@ -28,6 +28,11 @@ Permission is granted to copy and distribute translations of this manual into another language, under the same conditions as for modified versions. @end titlepage +@dircategory Math +@direntry +* Communications: (comms). Communications Toolbox for Octave +@end direntry + @contents @ifnottex -- cgit v1.2.3 From e82f88fde040c214a1f1a947322040cb8c3984c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Laboissi=C3=A8re?= Date: Mon, 24 Jan 2022 01:31:44 -0300 Subject: Add seed for random number generators Forwarded: https://savannah.gnu.org/bugs/index.php?48655 Last-Update: 2016-07-28 This patch add seeds for the random number generators used when building the PDF figures of the manual. This ensures that the data appearing in the figures is reproducible. Gbp-Pq: Name random-seed-for-pdf-doc.patch --- doc/commsimages.m | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/doc/commsimages.m b/doc/commsimages.m index 36eca98..83a239f 100644 --- a/doc/commsimages.m +++ b/doc/commsimages.m @@ -28,10 +28,12 @@ function commsimages (nm, typ) d_typ = ["-d", typ]; endif + seed = 1234; + if (strcmp (nm, "awgn")) x = 0:0.1:2*pi; y = sin (x); - noisy = awgn (y, 10, "measured"); + noisy = awgn (y, 10, "measured", [], seed); plot (x, y, "r"); hold on; plot (x, noisy, "g--"); @@ -42,9 +44,9 @@ function commsimages (nm, typ) ovsp = 50; x = 1:n; xi = 1:1/ovsp:n-0.1; - y = randsrc (1, n, [1 + 1i, 1 - 1i, -1 - 1i, -1 + 1i]); + y = randsrc (1, n, [1 + 1i, 1 - 1i, -1 - 1i, -1 + 1i], seed); yi = interp1 (x, y, xi); - noisy = awgn (yi, 15, "measured"); + noisy = awgn (yi, 15, "measured", [], seed); cf = gcf (); set (cf, "tag", "eyediagram"); eyediagram (noisy, ovsp, [], [], [], cf); @@ -54,9 +56,9 @@ function commsimages (nm, typ) ovsp = 5; x = 1:n; xi = 1:1/ovsp:n-0.1; - y = randsrc (1, n, [1 + 1i, 1 - 1i, -1 - 1i, -1 + 1i]); + y = randsrc (1, n, [1 + 1i, 1 - 1i, -1 - 1i, -1 + 1i], seed); yi = interp1 (x, y, xi); - noisy = awgn (yi, 15, "measured"); + noisy = awgn (yi, 15, "measured", [], seed); cf = gcf (); set (cf, "tag", "scatterplot"); f = scatterplot (noisy, 1, 0, "b", cf); -- cgit v1.2.3 From ecc2581aff69eb1ef1788e609d733f90da4b0b0f Mon Sep 17 00:00:00 2001 From: Rafael Laboissiere Date: Sun, 26 Jun 2022 19:14:12 -0300 Subject: Add category directory entry for the info documentation Forwarded: not-needed Last-Update: 2012-03-12 This is a requirement in Debian. Gbp-Pq: Name info-dir-section.patch --- doc/comms.txi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/comms.txi b/doc/comms.txi index 9088de9..c34b1b1 100644 --- a/doc/comms.txi +++ b/doc/comms.txi @@ -28,6 +28,11 @@ Permission is granted to copy and distribute translations of this manual into another language, under the same conditions as for modified versions. @end titlepage +@dircategory Math +@direntry +* Communications: (comms). Communications Toolbox for Octave +@end direntry + @contents @ifnottex -- cgit v1.2.3 From 1094ca0f076c412d7b93b2b6f8fcd615019904c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Laboissi=C3=A8re?= Date: Sun, 26 Jun 2022 19:14:12 -0300 Subject: Add seed for random number generators Forwarded: https://savannah.gnu.org/bugs/index.php?48655 Last-Update: 2016-07-28 This patch add seeds for the random number generators used when building the PDF figures of the manual. This ensures that the data appearing in the figures is reproducible. Gbp-Pq: Name random-seed-for-pdf-doc.patch --- doc/commsimages.m | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/doc/commsimages.m b/doc/commsimages.m index 36eca98..83a239f 100644 --- a/doc/commsimages.m +++ b/doc/commsimages.m @@ -28,10 +28,12 @@ function commsimages (nm, typ) d_typ = ["-d", typ]; endif + seed = 1234; + if (strcmp (nm, "awgn")) x = 0:0.1:2*pi; y = sin (x); - noisy = awgn (y, 10, "measured"); + noisy = awgn (y, 10, "measured", [], seed); plot (x, y, "r"); hold on; plot (x, noisy, "g--"); @@ -42,9 +44,9 @@ function commsimages (nm, typ) ovsp = 50; x = 1:n; xi = 1:1/ovsp:n-0.1; - y = randsrc (1, n, [1 + 1i, 1 - 1i, -1 - 1i, -1 + 1i]); + y = randsrc (1, n, [1 + 1i, 1 - 1i, -1 - 1i, -1 + 1i], seed); yi = interp1 (x, y, xi); - noisy = awgn (yi, 15, "measured"); + noisy = awgn (yi, 15, "measured", [], seed); cf = gcf (); set (cf, "tag", "eyediagram"); eyediagram (noisy, ovsp, [], [], [], cf); @@ -54,9 +56,9 @@ function commsimages (nm, typ) ovsp = 5; x = 1:n; xi = 1:1/ovsp:n-0.1; - y = randsrc (1, n, [1 + 1i, 1 - 1i, -1 - 1i, -1 + 1i]); + y = randsrc (1, n, [1 + 1i, 1 - 1i, -1 - 1i, -1 + 1i], seed); yi = interp1 (x, y, xi); - noisy = awgn (yi, 15, "measured"); + noisy = awgn (yi, 15, "measured", [], seed); cf = gcf (); set (cf, "tag", "scatterplot"); f = scatterplot (noisy, 1, 0, "b", cf); -- cgit v1.2.3 From 8d1f68a3c78160e0e6b3a1a0233c36a82b278800 Mon Sep 17 00:00:00 2001 From: Rafael Laboissiere Date: Sun, 10 Jul 2022 04:32:17 -0300 Subject: Add category directory entry for the info documentation Forwarded: not-needed Last-Update: 2012-03-12 This is a requirement in Debian. Gbp-Pq: Name info-dir-section.patch --- doc/comms.txi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/comms.txi b/doc/comms.txi index 9088de9..c34b1b1 100644 --- a/doc/comms.txi +++ b/doc/comms.txi @@ -28,6 +28,11 @@ Permission is granted to copy and distribute translations of this manual into another language, under the same conditions as for modified versions. @end titlepage +@dircategory Math +@direntry +* Communications: (comms). Communications Toolbox for Octave +@end direntry + @contents @ifnottex -- cgit v1.2.3 From a4d8db58cacbcdf85334c083882030dc9e05408b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Laboissi=C3=A8re?= Date: Sun, 10 Jul 2022 04:32:17 -0300 Subject: Add seed for random number generators Forwarded: https://savannah.gnu.org/bugs/index.php?48655 Last-Update: 2016-07-28 This patch add seeds for the random number generators used when building the PDF figures of the manual. This ensures that the data appearing in the figures is reproducible. Gbp-Pq: Name random-seed-for-pdf-doc.patch --- doc/commsimages.m | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/doc/commsimages.m b/doc/commsimages.m index 36eca98..83a239f 100644 --- a/doc/commsimages.m +++ b/doc/commsimages.m @@ -28,10 +28,12 @@ function commsimages (nm, typ) d_typ = ["-d", typ]; endif + seed = 1234; + if (strcmp (nm, "awgn")) x = 0:0.1:2*pi; y = sin (x); - noisy = awgn (y, 10, "measured"); + noisy = awgn (y, 10, "measured", [], seed); plot (x, y, "r"); hold on; plot (x, noisy, "g--"); @@ -42,9 +44,9 @@ function commsimages (nm, typ) ovsp = 50; x = 1:n; xi = 1:1/ovsp:n-0.1; - y = randsrc (1, n, [1 + 1i, 1 - 1i, -1 - 1i, -1 + 1i]); + y = randsrc (1, n, [1 + 1i, 1 - 1i, -1 - 1i, -1 + 1i], seed); yi = interp1 (x, y, xi); - noisy = awgn (yi, 15, "measured"); + noisy = awgn (yi, 15, "measured", [], seed); cf = gcf (); set (cf, "tag", "eyediagram"); eyediagram (noisy, ovsp, [], [], [], cf); @@ -54,9 +56,9 @@ function commsimages (nm, typ) ovsp = 5; x = 1:n; xi = 1:1/ovsp:n-0.1; - y = randsrc (1, n, [1 + 1i, 1 - 1i, -1 - 1i, -1 + 1i]); + y = randsrc (1, n, [1 + 1i, 1 - 1i, -1 - 1i, -1 + 1i], seed); yi = interp1 (x, y, xi); - noisy = awgn (yi, 15, "measured"); + noisy = awgn (yi, 15, "measured", [], seed); cf = gcf (); set (cf, "tag", "scatterplot"); f = scatterplot (noisy, 1, 0, "b", cf); -- cgit v1.2.3