<?xml version="1.0" encoding="ISO-8859-1"?>

<!DOCTYPE Book SYSTEM "gapdoc.dtd">

<Book Name="guava">                           <!-- REQUIRED -->

  <!--             The title page                                 -->
<TitlePage>    
  
    <Title>            <!-- REQUIRED -->
          <Package>GUAVA</Package>
    </Title>
	
    <Subtitle>     	                                     <!-- OPTIONAL -->
       A &GAP;4 Package for computing with error-correcting codes
       &nbsp;
    </Subtitle>

    <Version>Version 3.16</Version>     <!-- OPTIONAL -->
<Author>
Jasper Cramwinckel
</Author>
<Author>
Erik Roijackers
</Author>
<Author>
Reinald Baart
</Author>
<Author>
Eric Minkes
</Author>
<Author>
Lea Ruscio
</Author>
<Author>
Robert L Miller
</Author>
<Author>
Tom Boothby
</Author>
<Author>
Cen (``CJ'') Tjhai 
</Author>
<Author>
David Joyner                  <!-- REQUIRED -->
<!--             &nbsp;  
         <Address>
	 Mathematics Department,<Br/>
	 U. S. Naval Academy,<Br/>
	 Annapolis, MD,<Br/>
         21402 USA.
	 </Address>
<Email>wdjoyner@gmail.com</Email> 
 -->
</Author> 
<Author>
Joe Fields (Maintainer)   
    <Address>
         Mathematics Department,<Br/>
         Southern Connecticut State University,<Br/>
         New Haven, CT,<Br/>
         06515 USA.
    </Address>
    <Email>fieldsj1@southernct.edu</Email> 
    <Homepage>http://giam.southernct.edu/</Homepage>
</Author> 
<Date>April, 2022</Date>    <!-- OPTIONAL -->
<Copyright>     <!-- OPTIONAL -->
<Package>GUAVA</Package>: &copyright; The GUAVA Group: 1992-2003
Jasper Cramwinckel, Erik Roijackers,Reinald Baart, Eric Minkes,
Lea Ruscio (for the tex version), Jeffrey Leon
&copyright; 2004 David Joyner, Cen Tjhai, Jasper Cramwinckel, Erik Roijackers,
Reinald Baart, Eric Minkes, Lea Ruscio.
&copyright; 2007 Robert L Miller, Tom Boothby
&copyright; 2009, 2012, 2016, 2018, 2022 Joe Fields

<P/>
<Package>GUAVA</Package> is released under the 
GNU General Public License (GPL).
<P/>
    <Package>GUAVA</Package> 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.
<P/>
    <Package>GUAVA</Package> 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.
<P/>
    You should have received a copy of the GNU General Public License
    along with <Package>GUAVA</Package>; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
<P/>
For more details, see 
<URL>https://www.fsf.org/licenses/gpl.html</URL>. 
<P/>
For many years
<Package>GUAVA</Package> has been released along with the 
``backtracking''
C programs of J. Leon. In one of his *.c files the following 
statements occur:
``Copyright (C) 1992 by Jeffrey S. Leon.  
This software may be used freely
for educational and research purposes.  
Any other use requires permission from the author.'' 
The following should now be appended:
``I, Jeffrey S. Leon, agree to license all the partition
backtrack code which I have written under the GPL
(www.fsf.org) as of this date, April 17, 2007.''
<P/>
<Package>GUAVA</Package> documentation: 
&copyright; Jasper Cramwinckel, Erik Roijackers, Reinald Baart, 
Eric Minkes, Lea Ruscio (for the tex version), Joe Fields,
David Joyner, Cen Tjhai.

   Permission is granted to copy, distribute and/or modify this document
   under the terms of the GNU Free Documentation License, Version 1.2
   or any later version published by the Free Software Foundation;
   with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.
   A copy of the license is included in the section entitled "GNU
   Free Documentation License".
</Copyright> 

 

<Acknowledgements>    <!-- OPTIONAL -->
   <P/>
<Package>GUAVA</Package> was originally written by Jasper Cramwinckel, 
Erik Roijackers, and Reinald Baart in the early-to-mid 
1990's as a final project during their study of Mathematics at the 
Delft University of Technology, Department of Pure Mathematics,
under the direction of Professor Juriaan Simonis. 
This work was continued in Aachen, at Lehrstuhl D fur Mathematik.
In version 1.3, new functions were added by Eric Minkes, also from Delft
University of Technology.
<P/>
JC, ER and RB would like to thank the GAP people at the RWTH Aachen for
their support, A.E. Brouwer for his advice and J. Simonis for his
supervision.
   <P/>
The GAP 4 version of <Package>GUAVA</Package> (versions 1.4 and 1.5)
was created by Lea Ruscio and (from 2001, starting with version 1.6, to
early 2009) was maintained by David Joyner, who (with the 
help of several students) added several new functions. Starting 
with version 2.7, the ``best linear code''
tables for binary codes have been updated. From 2009, 
starting with version 3.10, <Package>GUAVA</Package> has been maintained 
by Joe Fields.
For further details, see the CHANGES file in the
<Package>GUAVA</Package> directory, also available at 
<URL>https://gap-packages.github.io/guava/CHANGES.guava</URL>.
   <P/>
<P/>This documentation was prepared with the 
<Package>GAPDoc</Package> package of Frank L&#xfc;beck and Max Neunh&#xf6;ffer. 
The conversion from TeX to 
<Package>GAPDoc</Package>'s XML was done by David Joyner in 2004.
<P/>
Please send bug reports, suggestions and other comments about
<Package>GUAVA</Package> to 
<Email>support@gap-system.org</Email>. Currently known bugs and 
suggested <Package>GUAVA</Package> projects are listed on the
bugs and projects web page
<URL>https://gap-packages.github.io/guava/guava2do.html</URL>.
Older releases and further history can be found on the 
<Package>GUAVA</Package> web page
<URL>https://gap-packages.github.io/guava/</URL>.
<P/>
<E>Contributors</E>: Other than the authors listed on the title page,
the following people have contributed code to the <Package>GUAVA</Package> 
project: Alexander Hulpke, Steve Linton, Frank L&#xfc;beck, Aron Foster,
Wayne Irons, Clifton (Clipper) Lennon, Jason McGowan, Shuhong Gao, 
Greg Gamble and Jeffrey S. Leon.
<P/>
For documentation on Leon's programs, 
see the src/leon/doc subdirectory of <Package>GUAVA</Package>.

</Acknowledgements>
</TitlePage>              <!-- end of title page --> 

<TableOfContents/>                        <!-- OPTIONAL -->



  <!--                The document                        -->
<Body>                                    <!-- REQUIRED -->


<Chapter><Heading>Introduction</Heading>


<Section>
  <Heading>Introduction to the <Package>GUAVA</Package> package</Heading>

This is the manual of the GAP package <Package>GUAVA</Package>.
<Package>GUAVA</Package> contains many functions that allow one 
to perform computations relevant to the theory of error-correcting codes.  
This version of <Package>GUAVA</Package> 
requires GAP 4.4.5 or later.  The current version of <Package>GUAVA</Package> (3.13) was updated to work with GAP 4.7.9.

<P/>
The functions in <Package>GUAVA</Package> can be divided into three subcategories:

<List>
<Item>
Construction of codes:
<Package>GUAVA</Package> can construct unrestricted, linear and cyclic
codes. Information about the code, such as operations applicable 
to the code, is stored in a record-like
data structure called a GAP object.
</Item>

<Item>
Manipulations of codes:
Manipulations transform  one code into  another, or construct a new code
from two codes. The new code can  profit from the  data in the record of
the old code(s), so in these cases calculation time often decreases.
</Item>

<Item>
Computations of information about codes:
<Package>GUAVA</Package> can calculate important parameters
of codes quickly. The results are stored in the codes'
object components.
</Item>
</List>
<P/>
Except for the automorphism group and isomorphism
testing functions, which make use of J.S. Leon's 
programs (see <Cite Key="Leon91"/> and the documentation 
in the 'src/leon' subdirectory of the 'guava'
directory for some details), and
<Ref Func="MinimumWeight" Style="Number"/> function,
<Package>GUAVA</Package> is written in the GAP 
language, and runs on any system supporting GAP4.4 and above. 
Several algorithms that need the speed were integrated 
in the GAP kernel. 
<P/>
Good general references for error-correcting codes and the 
technical terms in this manual are MacWilliams and Sloane 
<Cite Key="MS83"/>
and also Huffman and Pless <Cite Key="HP03"/>. 

</Section>
  
<Section>
  <Heading>Installing <Package>GUAVA</Package></Heading>
<Label Name="Installing GUAVA"/>

The most recent version of GAP (4.8) comes complete with
all of the packages -- including <Package>GUAVA</Package>.
Thus the following instructions are not usually applicable
but may be needed in certain circumstances.

<P/>
To install <Package>GUAVA</Package>
unpack the archive  file
in a directory in the `pkg' hierarchy of your version of GAP 4.  
<P/>
After unpacking <Package>GUAVA</Package> 
the GAP-only part of <Package>GUAVA</Package> is installed.
The parts of <Package>GUAVA</Package>
depending on J. Leon's backtrack  programs  package
(for  computing  automorphism  groups)  are  only  available  in  a  UNIX-like
environment, where you should proceed as follows:
Go to the newly created `guava' directory and call  
<C>`./configure  /gappath'</C>
where <C>/gappath</C> is the path to the GAP 
home directory. So for example, if
you install the package in the main `pkg' directory call

<Verb>
./configure ../..
</Verb>

This will fetch the architecture type for which GAP has been  compiled
last and create a `Makefile'. Now call

<Verb>
make
</Verb>

to compile the binaries and install them in the appropriate place.

(For a Windows machine with CYGWIN installed -
see <URL>https://www.cygwin.com/</URL> - instructions for 
compiling Leon's binaries are likely to be similar to those above.
On a 64-bit SUSE linux computer, instead of the configure command above
- which will only compile the 32-bit binary - type
<Verb>
./configure ../.. --enable-libsuffix=64 
make
</Verb>
to compile Leon's program as a 64 bit native binary. This may also
work for other 64-bit linux distributions as well.)
<P/>
If it is not already installed, you should also install the GAP
package <Package>SONATA</Package>. You can download 
this from the GAP website and unpack it in the `pkg'
subdirectory.

<P/>
This completes the installation of <Package>GUAVA</Package>  
for a single architecture. If
you use this installation of <Package>GUAVA</Package> 
on different hardware platforms you
will have to compile the binaries for each  platform  separately.  

</Section>
  
<Section>
  <Heading>Loading <Package>GUAVA</Package></Heading>


After starting up GAP, the <Package>GUAVA</Package> 
package needs to be loaded. Load
<Package>GUAVA</Package> by typing at the GAP prompt:

<Example>
gap> LoadPackage( "guava" );
</Example>

If <Package>GUAVA</Package> isn't already in memory, it is 
loaded and the author information is displayed.
If you  are a frequent user of <Package>GUAVA</Package>, 
you might consider adding  <Package>GUAVA</Package> to the "PackagesToLoad" preference in your gap initialization file.
(Usually <F>gap.ini</F> which should be located in your
home directory.)  Type <F>GAPInfo.UserGapRoot;</F> at the GAP prompt to 
find the location of your initialization file.  If none exists, the command
<F>WriteGapIniFile();</F> will create a default <F>gap.ini</F> file which you 
can then modify. 

</Section>
</Chapter>

<Chapter><Heading>A First Tutorial in <Package>GUAVA</Package></Heading>
<Label Name="A First Tutorial in GUAVA"/>

An error-correcting code is essentially just a subset of the set
of all possible messages of a given length over some finite "alphabet."

<P/>
In algebraic coding theory, the "alphabet" is usually some finite field (very often GF(2)) and frequently the error-correcting code is chosen to be a vector subspace of the space of all row vectors of some fixed length <M>n</M>.
Such codes are known as <E>Linear Codes</E>, but, however a code is defined the
point is to have a collection of "codewords" that are said to be "in the code"
and any other word (row vectors that are <E>not</E> "in the code") will be 
assumed to be a codeword that has been mangled by the addition of noise.

<P/>
When a message is received that is not a codeword, we ask ourselves the question "Which codeword is closest to this message I've received?"  In other words we make the presumption that the received message is actually a codeword that has been changed in a relatively small number of positions -- and <E>we put them back the way they were supposed to be!</E>

<P/>
That process is called "decoding."   Developing codes that have efficient decoding algorithms is one of the central problems of algebraic coding theory.

<Section>
  <Heading>Working with codewords</Heading>

<P/>
So let's play around a bit.

<P/>
Start <Package>GAP</Package> in a terminal window, then issue the command

<Example>
gap> LoadPackage("guava");
</Example>

<P/>
<Package>GUAVA</Package> can construct codewords in a variety of ways. One
of the most typical cases is for a codeword to consist of binary digits.  
In that case we say that "the code is over GF(2)" and codewords can be constructed as follows:

<Example>
gap> c1:=Codeword("101010101");
[ 1 0 1 0 1 0 1 0 1 ]
gap> v:=Z(2)*[1,1,1,1,1,1,1,1,1];
[ Z(2)^0, Z(2)^0, Z(2)^0, Z(2)^0, Z(2)^0, Z(2)^0, Z(2)^0, Z(2)^0, Z(2)^0 ]
gap> c2:=Codeword(v);
[ 1 1 1 1 1 1 1 1 1 ]
gap> c3:=c1+c2;
[ 0 1 0 1 0 1 0 1 0 ]
gap> Weight(c1);
5
gap> Weight(c2);
9
gap> Weight(c3);
4
</Example>

<P/>
The previous excerpt from a <Package>GAP</Package> session shows that
codewords can be constructed from quoted strings or from vectors whose 
entries lie in a finite field.  We also see that codewords can be added
together and that there is a function called <F>Weight</F> which (if it 
isn't obvious) tells us how many entries in a codeword are non-zero.

<P/>
The <E>Hamming distance</E> is used extensively in coding theory.  It 
tells us in how many positions two codewords differ.  In 
<Package>GUAVA</Package> the Hamming distance is implemented by a function
called <F>DistanceCodeword</F>.

<Example>
gap> DistanceCodeword(c1, c2);
4
</Example>

<P/>
Note that the Hamming distance between <C>c1</C> and <C>c2</C> happens to
give the same value as the weight of their sum.  This is no coincidence
and has to do with the curious fact that in GF(2) adding and subtracting
are the same thing.

<P/>
A codeword can also be constructed using a polynomial.  Indeed, the internal 
representation of a codeword requires either a polynomial or a vector. There
are <Package>GUAVA</Package> functions that allow one to switch back and
forth between the two representations.

<Example>
gap> x:=Indeterminate(GF(2));
x_1
gap> c4:=Codeword(x^7+x^2+x+1);
x^7 + x^2 + x + 1
gap> VectorCodeword(c4);
&lt;an immutable GF2 vector of length 8&gt;
gap> Display(last);
[ Z(2)^0, Z(2)^0, Z(2)^0, 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), Z(2)^0 ]
gap> c5:=Codeword([1,0,0,0,0,0,1]);
[ 1 0 0 0 0 0 1 ]
gap> PolyCodeword(c5);
x_1^6+Z(2)^0
</Example>
</Section>

<Section>
  <Heading>Calculations with codes</Heading>

A code is fundamentally just a collection of codewords.  Sometimes a
code is merely a <E>set</E> of codewords.  Other times a code will be 
the vector space generated by some small set of codewords. 

<P/>
First let's build a code that is merely a set:

<Example>
gap> l:=["111000", "011100", "001110", "000111", "100011", "110001", "000000",$
[ "111000", "011100", "001110", "000111", "100011", "110001", "000000", 
  "111111" ]
gap> m:=Codeword(l,6,GF(2));    
[ [ 1 1 1 0 0 0 ], [ 0 1 1 1 0 0 ], [ 0 0 1 1 1 0 ], [ 0 0 0 1 1 1 ], 
  [ 1 0 0 0 1 1 ], [ 1 1 0 0 0 1 ], [ 0 0 0 0 0 0 ], [ 1 1 1 1 1 1 ] ]
gap> C1:=ElementsCode(m, GF(2));
a (6,8,1..6)2..3 user defined unrestricted code over GF(2)
gap> IsLinearCode(C1);
false
gap> WeightDistribution(C1);
[ 1, 0, 0, 6, 0, 0, 1 ]
</Example>

<P/>
In this example we first wrote out a list of strings, then
converted them into codewords over GF(2).  The call to <F>ElementsCode</F>
constructs a code from a list of elements.  It is possible that the set
of codewords we used actually is a vector space, but the call to 
<F>IsLinearCode</F> says no.  Finally the last function tells us that
there are 6 codewords of weight 3, and one each of weights 0 and 6 in
this code.

<P/>
A very useful feature of <Package>GUAVA</Package> is the ability
to construct random codes:

<Example>
gap> C:= RandomLinearCode(12,5,GF(2));
a  [12,5,?] randomly generated code over GF(2)
</Example>

<P/>
An error-correcting code's properties are fairly well captured
by three numbers which traditionally are referred to using the 
letters <M>n</M>, <M>k</M> and <M>d</M>.  We ask for a random code
by specifying <M>n</M> (the wordlength), and <M>k</M> (the code's
dimension) as well as the field which serves as the alphabet for 
the code.

<P/>
One of the most salient features of a code (a feature that determines
how good it will be at correcting errors) is its minimum weight, <M>d</M>.  
This 
is the smallest weight of any nonzero word in the code.  If we
wish to correct <M>m</M> errors we will need to have a minimum weight
of at least <M>2m+1</M>.

<Example>
gap> MinimumWeight(C);
3
</Example>

<P/>
This particular code would be capable of correcting single bit errors.

<P/>
Finally, one might be interested in the entire distribution of the weights
of the words in a code.  The weight distribution is a vector that tells us
how many words there are in a code with each possible weight between <M>0</M>
and <M>n</M>.

<Example>
gap> WeightDistribution(C);
[ 1, 0, 0, 2, 3, 6, 7, 6, 4, 2, 1, 0, 0 ]
</Example>


</Section>
</Chapter>




<Chapter>
<Heading>Codewords</Heading>
<Label Name="Codewords"/>

Let <M>GF(q)</M> denote a finite field with <M>q</M> (a prime power)
elements. A <E>code</E> is a subset <M>C</M> of some
finite-dimensional vector space <M>V</M> over <M>GF(q)</M>. The
<E>length</E> of <M>C</M> is the dimension of <M>V</M>.
Usually, <M>V=GF(q)^n</M> and the length is the number of 
coordinate entries. When <M>C</M> is itself a vector space 
over <M>GF(q)</M> then it is called a <E>linear code</E>
<Index>linear code</Index> and 
the <E>dimension</E> of <M>C</M> 
is its dimension as a vector space over <M>GF(q)</M>.
<P/>
In <Package>GUAVA</Package>, a `codeword' is a GAP record, 
with one of its components being an element in <M>V</M>.
Likewise, a `code' is a GAP record, 
with one of its components being a subset (or subspace with given
basis, if <M>C</M> is linear) of <M>V</M>.

<Example>
  gap> C:=RandomLinearCode(20,10,GF(4));
  a  [20,10,?] randomly generated code over GF(4)
  gap> c:=Random(C);
  [ 1 a 0 0 0 1 1 a^2 0 0 a 1 1 1 a 1 1 a a 0 ]
  gap> NamesOfComponents(C);
  [ "LeftActingDomain", "GeneratorsOfLeftOperatorAdditiveGroup", "WordLength",
    "GeneratorMat", "name", "Basis", "NiceFreeLeftModule", "Dimension", 
     "Representative", "ZeroImmutable" ]
  gap> NamesOfComponents(c);
  [ "VectorCodeword", "WordLength", "treatAsPoly" ]
  gap> c!.VectorCodeword;
  [ immutable compressed vector length 20 over GF(4) ] 
  gap> Display(last);
  [ Z(2^2), Z(2^2), Z(2^2), Z(2)^0, Z(2^2), Z(2^2)^2, 0*Z(2), Z(2^2), Z(2^2),
    Z(2)^0, Z(2^2)^2, 0*Z(2), 0*Z(2), Z(2^2), 0*Z(2), 0*Z(2), 0*Z(2), Z(2^2)^2,
    Z(2)^0, 0*Z(2) ]
  gap> C!.Dimension;
  10
</Example>
<!--
C:=RandomLinearCode(20,10,GF(4));
c:=Random(C);
NamesOfComponents(C);
NamesOfComponents(c);
c!.VectorCodeword;
Display(last);
C!.Dimension;
-->

Mathematically, a `codeword' is an element of a code <M>C</M>,
but in <Package>GUAVA</Package> the <C>Codeword</C> 
and <C>VectorCodeword</C> commands have implementations which do not check if
the codeword belongs to <M>C</M> (i.e., are independent
of the code itself). They exist primarily to make it
easier for the user to construct the associated GAP record.
Using these commands, one can enter into GAP
both a codeword <M>c</M> (belonging to <M>C</M>)
and a received word <M>r</M> (not belonging to <M>C</M>)
using the same command. The user can input codewords in different
formats (as strings, vectors, and polynomials), 
and output information is formatted in a readable way.
<P/>
A codeword <M>c</M> in a linear code <M>C</M> arises in practice by 
an initial encoding of a 'block' message
<M>m</M>, adding enough redundancy to recover <M>m</M> after 
<M>c</M> is transmitted via a 'noisy' communication medium. 
In <Package>GUAVA</Package>, for linear codes, 
the map <M>m\longmapsto c</M>
is computed using the command <C>c:=m*C</C> and
recovering <M>m</M> from <M>c</M> is obtained by the
command <C>InformationWord(C,c)</C>. These commands are explained 
more below.
<P/>
Many operations are available on codewords themselves,
although codewords also work together with codes 
(see chapter <Ref Label="Codes" Style="Number"/> on Codes).
<P/>
The first section describes how codewords are constructed (see 
<Ref Func="Codeword" Style="Number"/> and 
<Ref Func="IsCodeword" Style="Number"/>).
Sections <Ref Label="Comparisons of Codewords" Style="Number"/>  and
<Ref Label="Arithmetic Operations for Codewords" Style="Number"/>
describe the arithmetic operations applicable to codewords.
Section 
<Ref Label="convert Codewords to Vectors or Polynomials" Style="Number"/>
describe functions that convert codewords back to vectors or polynomials
(see 
<Ref Func="VectorCodeword" Style="Number"/> and 
<Ref Func="PolyCodeword" Style="Number"/>).
Section <Ref Label="Functions that Change the Display Form of a Codeword" 
Style="Number"/>  describe
functions  that  change  the   way   a   codeword   is   displayed   (see
<Ref Func="TreatAsVector" Style="Number"/> and 
<Ref Func="TreatAsPoly" Style="Number"/>).
Finally, Section <Ref Label="Other Codeword Functions" Style="Number"/> 
describes  a  function  to
generate a null word (see <Ref Func="NullWord" Style="Number"/>) 
and some functions for extracting
properties of codewords   
(see <Ref Func="DistanceCodeword" Style="Number"/>,   
<Ref Func="Support" Style="Number"/>
and <Ref Func="WeightCodeword" Style="Number"/>).


<Section>
<Heading>Construction of Codewords</Heading>
<Label Name="Construction of Codewords"/>

<ManSection>
<Func Name="Codeword" Arg=" obj [n] [F] "/>
		   
<Description>
<C>Codeword</C> returns a codeword or a list of codewords constructed from
<Arg>obj</Arg>. 
 The object <Arg>obj</Arg>  can be a vector, a string, a polynomial or  a
codeword. It may also be a list of those (even a mixed list).
<P/>
If a number <Arg>n</Arg> is specified, all constructed codewords 
have  length <Arg>n</Arg>. 
This is the only way to make sure that all elements of 
<Arg>obj</Arg> are converted to codewords of the same length. 
Elements of <Arg>obj</Arg> that are
longer than <Arg>n</Arg> are reduced in length by cutting of the last
positions. Elements of <Arg>obj</Arg> that are 
shorter than <Arg>n</Arg> are lengthened by
adding zeros at the end. If no <Arg>n</Arg> is specified, each constructed
codeword is handled individually.
<P/>
If a  Galois field <Arg>F</Arg> is specified, all  
codewords are constructed over
this field. This is the only way to make sure that all elements of
<Arg>obj</Arg>
are converted to the same field <Arg>F</Arg> 
(otherwise they are converted one by
one). Note that all elements of <Arg>obj</Arg> must have elements over 
<Arg>F</Arg> or over `Integers'.  
Converting  from  one  Galois field to another is not
allowed. If no <Arg>F</Arg> is specified, vectors or 
strings with integer elements
will be converted to the smallest Galois field possible.
<P/>
Note that a significant speed increase is achieved  
if <Arg>F</Arg> is specified,
even when all elements of <Arg>obj</Arg> already have 
elements over <Arg>F</Arg>.
<P/>
Every vector in <Arg>obj</Arg> can be a finite field vector over 
<Arg>F</Arg> or a vector over `Integers'. In the last case, it is converted to 
<Arg>F</Arg> or, if omitted, to the smallest Galois field possible.
<P/>
Every string in <Arg>obj</Arg> must be a string of numbers, 
without spaces, commas
or any other characters. These numbers must be from 0 to 9. The string is
converted to a codeword over <Arg>F</Arg> or, 
if <Arg>F</Arg> is omitted, over the smallest
Galois  field  possible. Note that since all numbers in the string are
interpreted as one-digit numbers, Galois fields of size larger than  10
are not properly represented when using strings. In fact, no 
finite field of size larger than 11 arises in this fashion at all.
<P/>
Every polynomial in <Arg>obj</Arg> is converted to a codeword of 
length <Arg>n</Arg> or, if
omitted, of a length dictated by the degree of the polynomial. 
If <Arg>F</Arg> is specified, a polynomial in 
<Arg>obj</Arg> must be over <Arg>F</Arg>.
<P/>
Every element of <Arg>obj</Arg> that is already a codeword  is 
changed to  a codeword of length <Arg>n</Arg>. 
If no <Arg>n</Arg> was specified, the 
codeword doesn't change. If <Arg>F</Arg> is specified, 
the codeword must have base field <Arg>F</Arg>.

 <Example>
gap> c := Codeword([0,1,1,1,0]);
[ 0 1 1 1 0 ]
gap> VectorCodeword( c ); 
[ 0*Z(2), Z(2)^0, Z(2)^0, Z(2)^0, 0*Z(2) ]
gap> c2 := Codeword([0,1,1,1,0], GF(3));
[ 0 1 1 1 0 ]
gap> VectorCodeword( c2 );
[ 0*Z(3), Z(3)^0, Z(3)^0, Z(3)^0, 0*Z(3) ]
gap> Codeword([c, c2, "0110"]);
[ [ 0 1 1 1 0 ], [ 0 1 1 1 0 ], [ 0 1 1 0 ] ]
gap> p := UnivariatePolynomial(GF(2), [Z(2)^0, 0*Z(2), Z(2)^0]);
Z(2)^0+x_1^2
gap> Codeword(p);
x^2 + 1 
</Example>
<!--
c := Codeword([0,1,1,1,0]);
VectorCodeword( c ); 
c2 := Codeword([0,1,1,1,0], GF(3));
VectorCodeword( c2 );
Codeword([c, c2, "0110"]);
p := UnivariatePolynomial(GF(2), [Z(2)^0, 0*Z(2), Z(2)^0]);
Codeword(p);
-->

<P/>
This command can also be called using the syntax
<C>Codeword(obj,C)</C>.
In this format, the elements of <Arg>obj</Arg>
are converted to elements of the
same ambient vector space as the elements of a code <Arg>C</Arg>. 
The command <C>Codeword(c,C)</C> 
is the same  as calling  <C>Codeword(c,n,F)</C>, where
<Arg>n</Arg> is the word length of <Arg>C</Arg>
and the <Arg>F</Arg> is the ground field of <Arg>C</Arg>.
        </Description>
</ManSection>			  

 <Example>
gap> C := WholeSpaceCode(7,GF(5));
a cyclic [7,7,1]0 whole space code over GF(5)
gap> Codeword(["0220110", [1,1,1]], C);
[ [ 0 2 2 0 1 1 0 ], [ 1 1 1 0 0 0 0 ] ]
gap> Codeword(["0220110", [1,1,1]], 7, GF(5));
[ [ 0 2 2 0 1 1 0 ], [ 1 1 1 0 0 0 0 ] ] 
gap> C:=RandomLinearCode(10,5,GF(3));
a linear [10,5,1..3]3..5 random linear code over GF(3)
gap> Codeword("1000000000",C);
[ 1 0 0 0 0 0 0 0 0 0 ]
gap> Codeword("1000000000",10,GF(3));
[ 1 0 0 0 0 0 0 0 0 0 ]
</Example>
<!--
C := WholeSpaceCode(7,GF(5));
Codeword(["0220110", [1,1,1]], C);
Codeword(["0220110", [1,1,1]], 7, GF(5));
C:=RandomLinearCode(10,5,GF(3));
Codeword("1000000000",C);
Codeword("1000000000",10,GF(3));
-->

<ManSection>

<Func Name="CodewordNr" Arg=" C list "/>
		   
        <Description>
<C>CodewordNr</C> returns a list of codewords of <Arg>C</Arg>. 
<Arg>list</Arg> may  be a list of
integers  or a single   integer.   For   each  integer  of 
<Arg>list</Arg>, the
corresponding codeword of <Arg>C</Arg> is returned. 
The correspondence of a number
<M>i</M> with a codeword is determined as follows: if a list of elements of
<Arg>C</Arg>  is  available, the <M>i^{th}</M> 
element is taken.  Otherwise, it is
calculated by multiplication of the <M>i^{th}</M> information vector  by the
generator matrix or generator  polynomial, where the  information vectors
are ordered lexicographically. In particular, the returned
codeword(s) could be a vector or a polynomial.

So <C>CodewordNr(C, i)</C> is equal to 
<C>AsSSortedList(C)[i]</C>, described in the next chapter.  
The latter function first calculates the set of all 
the elements of <M>C</M> and then
returns the  <M>i^{th}</M> element of that set, whereas the 
former only calculates the <M>i^{th}</M> codeword.
        </Description>
</ManSection>			  

<Example>
gap> B := BinaryGolayCode();
a cyclic [23,12,7]3 binary Golay code over GF(2)
gap> c := CodewordNr(B, 4);
x^22 + x^20 + x^17 + x^14 + x^13 + x^12 + x^11 + x^10
gap> R := ReedSolomonCode(2,2);
a cyclic [2,1,2]1 Reed-Solomon code over GF(3)
gap> AsSSortedList(R);
[ [ 0 0 ], [ 1 1 ], [ 2 2 ] ]
gap> CodewordNr(R, [1,3]);
[ [ 0 0 ], [ 2 2 ] ]
</Example>
<!--
B := BinaryGolayCode();
c := CodewordNr(B, 4);
R := ReedSolomonCode(2,2);
AsSSortedList(R);
CodewordNr(R, [1,3]);
-->

<ManSection>
   <Func Name="IsCodeword" Arg=" obj "/>
		   
<Description>
<C>IsCodeword</C> returns `true' if <Arg>obj</Arg>, 
which can be an object of arbitrary
type, is of  the codeword type and `false'  otherwise.  The function will
signal an error if <Arg>obj</Arg> is an unbound variable.
</Description>
</ManSection>			  

<Example>
gap> IsCodeword(1);
false
gap> IsCodeword(ReedMullerCode(2,3));
false
gap> IsCodeword("11111");
false
gap> IsCodeword(Codeword("11111"));
true 
</Example>
<!--
IsCodeword(1);
IsCodeword(ReedMullerCode(2,3));
IsCodeword("11111");
IsCodeword(Codeword("11111"));
-->


</Section>


<Section>
<Heading>Comparisons of Codewords</Heading>
<Label Name="Comparisons of Codewords"/>

<ManSection>
<Meth Name="\=" Label="for codewords" Arg=" c1 c2"/>
		   
<Description>
The equality operator <C>c1 = c2</C>
evaluates to `true' if the codewords 
<A>c1</A>
and <A>c2</A> are equal, and to  `false' otherwise. 
Note  that codewords are  equal if  and only  if  their base  vectors are
equal.   Whether they  are  represented  as a vector  or  polynomial  has
nothing to do with the comparison.
<P/>
Comparing codewords with objects of other types is not recommended,
although it is  possible. If <A>c2</A> is  the  codeword, the  other object
<A>c1</A>  is first  converted to a   codeword, after  which  comparison is
possible. This way, a codeword can be compared with a vector, polynomial,
or string. If <A>c1</A> is the codeword, then problems may arise if 
<A>c2</A> is a polynomial.  In that case, the comparison always 
yields  a `false', because the polynomial comparison is called.
<P/>
The equality operator is also denoted <C>EQ</C>, and
<C>EQ(c1,c2)</C> is the same as <C>c1 = c2</C>.
There is also an inequality operator, &tlt; &tgt;,
or <C>not EQ</C>.

<Index>not =</Index>
<Index>&tlt; &tgt;</Index>
       </Description>
</ManSection>			  

<Example>
gap> P := UnivariatePolynomial(GF(2), Z(2)*[1,0,0,1]);
Z(2)^0+x_1^3
gap> c := Codeword(P, GF(2));
x^3 + 1
gap> P = c;        # codeword operation
true
gap> c2 := Codeword("1001", GF(2));
[ 1 0 0 1 ]
gap> c = c2;
true 
gap> C:=HammingCode(3);
a linear [7,4,3]1 Hamming (3,2) code over GF(2)
gap> c1:=Random(C);
[ 1 0 0 1 1 0 0 ]
gap> c2:=Random(C);
[ 0 1 0 0 1 0 1 ]
gap> EQ(c1,c2);
false
gap> not EQ(c1,c2);
true
</Example>
<!--
P := UnivariatePolynomial(GF(2), Z(2)*[1,0,0,1]);
c := Codeword(P, GF(2));
P = c;        # codeword operation
c2 := Codeword("1001", GF(2));
c = c2;
C:=HammingCode(3);
c1:=Random(C);
c2:=Random(C);
EQ(c1,c2);
not EQ(c1,c2);
-->

</Section>


<Section>
<Heading>Arithmetic Operations for Codewords</Heading>
<Label Name="Arithmetic Operations for Codewords"/>

<ManSection>
<Meth Name="\+" Label="for codewords" Arg="c1 c2"/>
		   
<Description>
The following operations are always available for codewords. The operands
must have a common base field, and must have the same length. No implicit
conversions are performed.
<Index>codewords, addition</Index>
<P/>
The operator  <C>+</C>  evaluates to the sum of the codewords <A>c1</A> 
and <A>c2</A>.
</Description>
</ManSection>

<Example>
gap> C:=RandomLinearCode(10,5,GF(3));
a linear [10,5,1..3]3..5 random linear code over GF(3)
gap> c:=Random(C);
[ 1 0 2 2 2 2 1 0 2 0 ]
gap> Codeword(c+"2000000000");
[ 0 0 2 2 2 2 1 0 2 0 ]
gap> Codeword(c+"1000000000");
</Example>
<!--
C:=RandomLinearCode(10,5,GF(3));
c:=Random(C);
Codeword(c+"2000000000");
Codeword(c+"1000000000");
-->
The last command returns a GAP ERROR since 
the `codeword' which <Package>GUAVA</Package>
associates to "1000000000" belongs to <M>GF(2)</M>
and not <M>GF(3)</M>.


<ManSection>
<Meth Name="\-" Label="for codewords" Arg="c1 c2"/>
		   
<Description>
Similar to addition:
the operator <C>-</C> evaluates to the difference of the codewords 
<A>c1</A> and <A>c2</A>.
<Index>codewords, subtraction</Index>
</Description>
</ManSection>

<ManSection>
<Meth Name="\+" Label="for codeword and code" Arg="v C"/>

<Description>
The operator <C>v+C</C> evaluates to the coset code of code <A>C</A> 
after adding a `codeword' <A>v</A> to all codewords in <A>C</A>. 
Note that if <M>c \in C</M> then mathematically
<M>c+C=C</M> but <Package>GUAVA</Package> only
sees them equal as <E>sets</E>. 
See <Ref Func="CosetCode" Style="Number"/>.
<P/>
Note that the command <C>C+v</C> returns the same output
as the command <C>v+C</C>.
<P/>
<Index>codewords, cosets</Index>
</Description>
</ManSection>
<Index>coset</Index>

<Example>
gap> C:=RandomLinearCode(10,5);
a  [10,5,?] randomly generated code over GF(2)
gap> c:=Random(C);
[ 0 0 0 0 0 0 0 0 0 0 ]
gap> c+C;
[ add. coset of a  [10,5,?] randomly generated code over GF(2) ]
gap> c+C=C;
true
gap> IsLinearCode(c+C);
false
gap> v:=Codeword("100000000");
[ 1 0 0 0 0 0 0 0 0 ]
gap> v+C;
[ add. coset of a  [10,5,?] randomly generated code over GF(2) ]
gap> C=v+C;
false
gap> C := GeneratorMatCode( [ [1, 0,0,0], [0, 1,0,0] ], GF(2) );
a linear [4,2,1]1 code defined by generator matrix over GF(2)
gap> Elements(C);
[ [ 0 0 0 0 ], [ 0 1 0 0 ], [ 1 0 0 0 ], [ 1 1 0 0 ] ]
gap> v:=Codeword("0011");
[ 0 0 1 1 ]
gap> C+v;
[ add. coset of a linear [4,2,4]1 code defined by generator matrix over GF(2) ]
gap> Elements(C+v);
[ [ 0 0 1 1 ], [ 0 1 1 1 ], [ 1 0 1 1 ], [ 1 1 1 1 ] ]
</Example>
<!--
C:=RandomLinearCode(10,5);
c:=Random(C);
c+C;
c+C=C;
IsLinearCode(c+C);
v:=Codeword("100000000");
v+C;
C=v+C;
C := GeneratorMatCode( [ [1, 0,0,0], [0, 1,0,0] ], GF(2) );
Elements(C);
v:=Codeword("0011");
C+v;
Elements(C+v);
-->


In general, the operations just described can also be performed on
codewords expressed as vectors, strings or polynomials, 
although this is not recommended. The
vector, string  or polynomial is first converted to a codeword, after
which the normal operation is performed. For this to go right, make sure
that at least one of the operands is a codeword. Further more, it will
not work when the right operand is a polynomial. In that case, the
polynomial operations (<C>FiniteFieldPolynomialOps</C>) are called, instead of
the codeword operations (<C>CodewordOps</C>).
<P/>
Some other code-oriented operations with codewords are described in
<Ref Subsect="Operations for Codes" Style="Number"/>.		  

</Section>

<Section>
<Heading>
Functions that Convert Codewords to Vectors or Polynomials
</Heading>
<Label Name="convert Codewords to Vectors or Polynomials"/>


<ManSection>
<Func Name="VectorCodeword" Arg="obj"/>
		   
<Description>
Here <A>obj</A> can be a code word or a list of code words. This function
returns the corresponding vectors over a finite field.
       </Description>
</ManSection>			  

<Example>
gap> a := Codeword("011011");; 
gap> VectorCodeword(a);
[ 0*Z(2), Z(2)^0, Z(2)^0, 0*Z(2), Z(2)^0, Z(2)^0 ]
</Example>
<!--
a := Codeword("011011");; 
VectorCodeword(a);
-->

<ManSection>
<Func Name="PolyCodeword" Arg="obj"/>
		   
<Description>
<C>PolyCodeword</C> returns a polynomial or a list 
of polynomials over a Galois field, converted from <A>obj</A>. 
The object <A>obj</A> can be a codeword, or a list of codewords.
</Description>
</ManSection>			  

<Example>
gap> a := Codeword("011011");; 
gap> PolyCodeword(a);
x_1+x_1^2+x_1^4+x_1^5
</Example>
<!--
a := Codeword("011011");; 
PolyCodeword(a);
-->

</Section>

<Section>
<Heading>
Functions that Change the Display Form of a Codeword
</Heading>
<Label Name="Functions that Change the Display Form of a Codeword"/>

<ManSection>
<Func Name="TreatAsVector" Arg="obj"/>
		   
<Description>
<C>TreatAsVector</C> adapts the codewords in 
<A>obj</A> to make sure they are printed as vectors. 
<A>obj</A> may be a codeword or a list of codewords.  
Elements of <A>obj</A> that are not codewords are ignored. After
this function is called, the codewords will be treated as vectors. The
vector representation is obtained by using the coefficient list of the
polynomial.
<P/>
Note that this <E>only</E> changes the way a codeword is <E>printed</E>.
<C>TreatAsVector</C> returns nothing, it is called only for its side effect.
The  function <C>VectorCodeword</C> converts codewords to vectors (see
<Ref Func="VectorCodeword" Style="Number"/>).
</Description>
</ManSection>			  

<Example>
gap> B := BinaryGolayCode();
a cyclic [23,12,7]3 binary Golay code over GF(2)
gap> c := CodewordNr(B, 4);
x^22 + x^20 + x^17 + x^14 + x^13 + x^12 + x^11 + x^10
gap> TreatAsVector(c);
gap> c;
[ 0 0 0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 1 0 0 1 0 1 ] 
</Example>
<!--
B := BinaryGolayCode();
c := CodewordNr(B, 4);
TreatAsVector(c);
c;
-->

<ManSection>
<Func Name="TreatAsPoly" Arg="obj"/>
		   
<Description>
<C>TreatAsPoly</C> adapts the codewords in <A>obj</A> 
to make sure they are printed
as polynomials. <A>obj</A> may be a codeword or a list of codewords. Elements
of <A>obj</A> that are not codewords are ignored.  After this function is
called, the codewords will be treated as polynomials. The finite field
vector that defines the codeword is used as a coefficient list of the
polynomial representation,  where the first element of the vector is the
coefficient of degree zero, the second element is the coefficient of
degree one, etc, until the last element, which is the coefficient of
highest degree.
<P/>
Note that this <E>only</E> changes the way a codeword is 
<E>printed</E>.  <C>TreatAsPoly</C>
returns nothing,  it is called only for its side effect. The function
<C>PolyCodeword</C> converts codewords to polynomials 
(see <Ref Func="PolyCodeword" Style="Number"/>).
</Description>
</ManSection>			  

<Example>
gap> a := Codeword("00001",GF(2));
[ 0 0 0 0 1 ]
gap> TreatAsPoly(a); a;
x^4
gap> b := NullWord(6,GF(4));
[ 0 0 0 0 0 0 ]
gap> TreatAsPoly(b); b;
0 
</Example>
<!--
a := Codeword("00001",GF(2));
TreatAsPoly(a); a;
b := NullWord(6,GF(4));
TreatAsPoly(b); b;
-->

</Section>

<Section>
<Heading>
Other Codeword Functions
</Heading>
<Label Name="Other Codeword Functions"/>


<ManSection>
<Func Name="NullWord" Arg="n F"/>
		   
<Description>
Other uses: <C>NullWord( n )</C> (default <M>F=GF(2)</M>)
and <C>NullWord( C )</C>.

<C>NullWord</C> returns a codeword of length <A>n</A> over the 
field <A>F</A> of only zeros.  The integer
<A>n</A> must be greater then zero. If
only a code <Arg>C</Arg> is specified, <C>NullWord</C> 
will return a null word with both the
word length and the Galois field of <Arg>C</Arg>.
</Description>
</ManSection>			  

<Example>
gap> NullWord(8);
[ 0 0 0 0 0 0 0 0 ]
gap> Codeword("0000") = NullWord(4);
true
gap> NullWord(5,GF(16));
[ 0 0 0 0 0 ]
gap> NullWord(ExtendedTernaryGolayCode());
[ 0 0 0 0 0 0 0 0 0 0 0 0 ] 
</Example>
<!--
NullWord(8);
Codeword("0000") = NullWord(4);
NullWord(5,GF(16));
NullWord(ExtendedTernaryGolayCode());
-->

<ManSection>
<Func Name="DistanceCodeword" Arg="c1 c2"/>
		   
<Description>
<C>DistanceCodeword</C> returns the Hamming distance from 
<A>c1</A> to <A>c2</A>. Both
variables  must be codewords with equal word length over the same Galois
field. The Hamming distance between two words is the number of places in
which they differ. As a result, <C>DistanceCodeword</C>  
always returns an integer between zero and the word length of the codewords.
</Description>
</ManSection>			  

<Example>
gap> a := Codeword([0, 1, 2, 0, 1, 2]);; b := NullWord(6, GF(3));;
gap> DistanceCodeword(a, b);
4
gap> DistanceCodeword(b, a);
4
gap> DistanceCodeword(a, a);
0 
</Example>
<!--
a := Codeword([0, 1, 2, 0, 1, 2]);; b := NullWord(6, GF(3));;
DistanceCodeword(a, b);
DistanceCodeword(b, a);
DistanceCodeword(a, a);
-->

<ManSection>
<Func Name="Support" Arg="c"/>
		   
<Description>
<C>Support</C> returns a set of integers indicating the positions of 
the non-zero entries in a codeword <A>c</A>.
</Description>
</ManSection>			  

<Example>
gap> a := Codeword("012320023002");; Support(a);
[ 2, 3, 4, 5, 8, 9, 12 ]
gap> Support(NullWord(7));
[  ] 
</Example>
<!--
a := Codeword("012320023002");; Support(a);
Support(NullWord(7));
-->

The support of a list with codewords can be calculated by taking the
union of the individual supports. The weight of the support is the length
of the set.

<Example>
gap> L := Codeword(["000000", "101010", "222000"], GF(3));;
gap> S := Union(List(L, i -> Support(i)));
[ 1, 2, 3, 5 ]
gap> Length(S);
4 
</Example>
<!--
L := Codeword(["000000", "101010", "222000"], GF(3));;
S := Union(List(L, i -> Support(i)));
Length(S);
-->

<ManSection>
<Func Name="WeightCodeword" Arg="c"/>
		   
<Description>
<C>WeightCodeword</C> returns the weight of a codeword 
<M>c</M>, the number of non-zero entries in <A>c</A>. 
As a result, <C>WeightCodeword</C> always returns an
integer between zero and the word length of the codeword.
</Description>
</ManSection>			  

<Example>
gap> WeightCodeword(Codeword("22222"));
5
gap> WeightCodeword(NullWord(3));
0
gap> C := HammingCode(3);
a linear [7,4,3]1 Hamming (3,2) code over GF(2)
gap> Minimum(List(AsSSortedList(C){[2..Size(C)]}, WeightCodeword ) );
3 
</Example>
<!--
WeightCodeword(Codeword("22222"));
WeightCodeword(NullWord(3));
C := HammingCode(3);
Minimum(List(AsSSortedList(C){[2..Size(C)]}, WeightCodeword ) );
-->

</Section>

</Chapter>

<Chapter>
<Heading>Codes</Heading>
<Label Name="Codes"/>

A <E>code</E> is a set of codewords (recall a
<Index>code</Index>
<Index>code, elements of</Index>
codeword in <Package>GUAVA</Package> is simply 
a sequence of elements of a finite field  
<M>GF(q)</M>, where <M>q</M> is  a  prime power). 
We  call these the <E>elements</E> of the code. 
Depending on the type of code, a codeword can be interpreted as
a  vector or as a polynomial. 
This is explained in more detail in Chapter 
<Ref Label="Codewords" Style="Number"/>.
<P/>
In <Package>GUAVA</Package>, 
codes can be a set specified by its elements (this will be called
an <E>unrestricted code</E>), 
<Index>code, unrestricted</Index>
by a generator matrix listing a set of basis elements 
(for a linear code) or by a
generator polynomial (for a cyclic code).
<P/>
Any code can be defined by its elements. If you like, you can give the
code a name.

<Example>
gap> C := ElementsCode(["1100", "1010", "0001"], "example code", GF(2) );
a (4,3,1..4)2..4 example code over GF(2) 
</Example>

An <M>(n,M,d)</M> code is a code with word <E>length</E> 
<M>n</M>,  <E>size</E> <M>M</M> and
<E>minimum distance</E> <M>d</M>. 
<Index>
code, <M>(n,M,d)</M> 
</Index>
<Index>
minimum  distance
</Index>
<Index>
length
</Index>
<Index>
size
</Index>
If the minimum distance has not yet been
calculated, the lower bound and upper bound are printed
(except in the case where the code is a random linear codes,
where these are not printed for efficiency reasons). So

<Verb>
a (4,3,1..4)2..4 code over GF(2)
</Verb>
means a binary unrestricted code of length <M>4</M>, with <M>3</M> 
elements and the minimum distance is greater than or equal to 
<M>1</M> and less than or equal to <M>4</M> 
and the covering radius is greater than or equal to <M>2</M> and less
than or equal to <M>4</M>.

<Example>
gap> C := ElementsCode(["1100", "1010", "0001"], "example code", GF(2) );
a (4,3,1..4)2..4 example code over GF(2) 
gap> MinimumDistance(C);
2
gap> C;
a (4,3,2)2..4 example code over GF(2) 
</Example>
<!--
C := ElementsCode(["1100", "1010", "0001"], "example code", GF(2) );
MinimumDistance(C);
C;
-->

If the set of elements is a linear subspace of <M>GF(q)^n</M>, 
the code is called <E>linear</E>. If a code is linear, it can be 
defined by its <E>generator matrix</E> or <E>parity check matrix</E>.  
<Index>code, linear</Index>
<Index>parity check matrix</Index>
By definition, 
the rows of the generator matrix is a basis for
the code (as a vector space over <M>GF(q)</M>).
By definition, 
the rows of the parity check matrix is a basis for the
dual space of the code,

<Display>
C^* = \{ v \in GF(q)^n\ |\ v\cdot c = 0,\ for \ all\ c \in C \}.
</Display>

<Example>
gap> G := GeneratorMatCode([[1,0,1],[0,1,2]], "demo code", GF(3) );
a linear [3,2,1..2]1 demo code over GF(3) 
</Example>

So a linear <M>[n,  k, d]r</M> code 
<Index>
code, <M>[n,  k, d]r</M>
</Index>
is a code with word <E>length</E> <M>n</M>,
<E>dimension</E> <M>k</M>, <E>minimum distance</E> 
<M>d</M> and <E>covering radius</E> <M>r</M>.
<P/>
If the code is linear and all cyclic shifts of its codewords 
(regarded as <M>n</M>-tuples) are again
codewords, the code is called <E>cyclic</E>.  
<Index>code, cyclic</Index>
All elements of a cyclic code are multiples
of the monic polynomial modulo a polynomial <M>x^n -1</M>,
where <M>n</M> is the word length of the code. 
Such a polynomial is called a <E>generator polynomial</E>
<Index>generator polynomial</Index>
The generator polynomial must divide <M>x^n-1</M> and its
quotient is called a <E>check polynomial</E>.
<Index>check polynomial</Index>
Multiplying a codeword in a cyclic code by the check
polynomial yields zero (modulo the polynomial <M>x^n -1</M>).
In <Package>GUAVA</Package>, a 
cyclic code can be defined by either its generator polynomial or 
check polynomial. 

<Example>
gap> G := GeneratorPolCode(Indeterminate(GF(2))+Z(2)^0, 7, GF(2) );
a cyclic [7,6,1..2]1 code defined by generator polynomial over GF(2)
</Example>

It is possible that <Package>GUAVA</Package>
does not know that an unrestricted code is in fact
linear. This situation occurs for example when a code is generated from a
list of elements with the function <C>ElementsCode</C> 
(see <Ref Func="ElementsCode" Style="Number"/>).
By calling the  function <C>IsLinearCode</C> (see
<Ref Func="IsLinearCode" Style="Number"/>), <Package>GUAVA</Package>
tests if the code can be represented by a generator matrix. 
If so, the code record and the operations are converted accordingly.

<Example>
gap> L := Z(2)*[ [0,0,0], [1,0,0], [0,1,1], [1,1,1] ];;
gap> C := ElementsCode( L, GF(2) );
a (3,4,1..3)1 user defined unrestricted code over GF(2)
# so far, GUAVA does not know what kind of code this is
gap> IsLinearCode( C );
true                      # it is linear
gap> C;
a linear [3,2,1]1 user defined unrestricted code over GF(2) 
</Example>
<!--
L := Z(2)*[ [0,0,0], [1,0,0], [0,1,1], [1,1,1] ];;
C := ElementsCode( L, GF(2) );
IsLinearCode( C );
C;
-->

Of course the same holds for unrestricted codes that in fact are cyclic,
or codes, defined by a generator matrix, that actually are cyclic.
<P/>
Codes are printed simply by giving a small description of their
parameters, the word  length, size or dimension and perhaps
the minimum  distance,
followed by a short description and the base field  of the code.   The
function <C>Display</C> gives a more detailed description, showing the
construction history of the code.
<P/>
<Package>GUAVA</Package> doesn't place much emphasis on the 
actual encoding and decoding
processes; some algorithms have been included  though.  Encoding works
simply by multiplying an information vector with a code, decoding is done
by the functions <C>Decode</C> or  <C>Decodeword</C>.  
For more information about encoding and
decoding, see sections 
<Ref Label="Operations for Codes" Style="Number"/> and 
<Ref Label="Decode" Style="Number"/>.

<Example>
gap> R := ReedMullerCode( 1, 3 );
a linear [8,4,4]2 Reed-Muller (1,3) code over GF(2)
gap> w := [ 1, 0, 1, 1 ] * R;
[ 1 0 0 1 1 0 0 1 ]
gap> Decode( R, w );
[ 1 0 1 1 ]
gap> Decode( R, w + "10000000" ); # One error at the first position
[ 1 0 1 1 ]                       # Corrected by Guava 
</Example>
<!--
R := ReedMullerCode( 1, 3 );
w := [ 1, 0, 1, 1 ] * R;
Decode( R, w );
Decode( R, w + "10000000" ); 
-->

Sections <Ref Label="Comparisons of Codes" Style="Number"/> and
<Ref Label="Operations for Codes" Style="Number"/>  describe  the
operations that are available for codes.

Section <Ref Label="Boolean Functions for Codes" Style="Number"/> describe 
the functions  that  tests
whether an object is a code and what kind of code it  is  (see <C>IsCode</C>,
<Ref Func="IsLinearCode" Style="Number"/> and <C>IsCyclicCode</C>) 
and various  other  boolean  functions for codes.

Section <Ref Label="Equivalence and Isomorphism of Codes" Style="Number"/> 
describe functions about equivalence and isomorphism of 
codes (see <Ref Func="IsEquivalent" Style="Number"/>,
<Ref Func="CodeIsomorphism" Style="Number"/> and 
<Ref Func="AutomorphismGroup" Style="Number"/>).

Section <Ref Label="Domain Functions for Codes" Style="Number"/> 
describes  functions  that  work  on
<E>domains</E> (see Chapter "Domains and their Elements" in the GAP
Reference Manual).

Section <Ref Label="Printing and Displaying Codes" Style="Number"/>
describes functions for  printing and displaying codes.

Section 
<Ref Label="Generating (Check) Matrices and Polynomials" Style="Number"/>
describes functions that return the matrices and polynomials  
that define a code (see
<Ref Func="GeneratorMat" Style="Number"/>, 
<Ref Func="CheckMat" Style="Number"/>, 
<Ref Func="GeneratorPol" Style="Number"/>, 
<Ref Func="CheckPol" Style="Number"/>, 
<Ref Func="RootsOfCode" Style="Number"/>).

Section <Ref Label="Parameters of Codes" Style="Number"/> 
describes functions that return the basic
parameters of codes (see <Ref Func="WordLength" Style="Number"/>, 
<Ref Func="Redundancy" Style="Number"/>   and
<Ref Func="MinimumDistance" Style="Number"/>).

Section <Ref Label="Distributions" Style="Number"/> 
describes functions that return distance and
weight distributions  (see  
<Ref Func="WeightDistribution" Style="Number"/>,   
<Ref Func="InnerDistribution" Style="Number"/>,
<Ref Func="OuterDistribution" Style="Number"/> and 
<Ref Func="DistancesDistribution" Style="Number"/>).

Section <Ref Label="Decoding Functions" Style="Number"/> 
describes  functions  that  are  related  to
decoding (see <Ref Func="Decode" Style="Number"/>, 
<Ref Func="Decodeword" Style="Number"/>, 
<Ref Func="Syndrome" Style="Number"/>, 
<Ref Func="SyndromeTable" Style="Number"/> and 
<Ref Func="StandardArray" Style="Number"/>).

In Chapters <Ref Label="Generating Codes" Style="Number"/> and
<Ref Label="Manipulating Codes" Style="Number"/> which follow,
we describe functions that generate and manipulate codes.

<Section>
<Heading>Comparisons of Codes</Heading>
<Label Name="Comparisons of Codes"/>

<ManSection>
<Meth Name="\=" Label="for codes" Arg=" C1 C2"/>
		   
<Description>
The equality operator <C>C1 = C2</C>
evaluates to `true' if the codes <A>C1</A>
and <A>C2</A> are equal, and to  `false' otherwise. 
<P/>
The equality operator is also denoted <C>EQ</C>, and
<C>Eq(C1,C2)</C> is the same as <C>C1 = C2</C>.
There is also an inequality operator, &tlt; &tgt;,
or <C>not EQ</C>.
<P/>
Note that codes are equal if and only if their set of elements are equal. Codes
can also  be compared with objects of other types.  Of course they are
never equal.
</Description>
</ManSection>	

<Index>not =</Index>
<Index>&tlt; &tgt;</Index>

<Example>
gap> M := [ [0, 0], [1, 0], [0, 1], [1, 1] ];;
gap> C1 := ElementsCode( M, GF(2) );
a (2,4,1..2)0 user defined unrestricted code over GF(2)
gap> M = C1;
false
gap> C2 := GeneratorMatCode( [ [1, 0], [0, 1] ], GF(2) );
a linear [2,2,1]0 code defined by generator matrix over GF(2)
gap> C1 = C2;
true
gap> ReedMullerCode( 1, 3 ) = HadamardCode( 8 );
true
gap> WholeSpaceCode( 5, GF(4) ) = WholeSpaceCode( 5, GF(2) );
false
</Example>
<!--
M := [ [0, 0], [1, 0], [0, 1], [1, 1] ];;
C1 := ElementsCode( M, GF(2) );
M = C1;
C2 := GeneratorMatCode( [ [1, 0], [0, 1] ], GF(2) );
C1 = C2;
ReedMullerCode( 1, 3 ) = HadamardCode( 8 );
WholeSpaceCode( 5, GF(4) ) = WholeSpaceCode( 5, GF(2) );
-->

Another way  of comparing codes is <C>IsEquivalent</C>, which checks if two
codes are equivalent (see <Ref Func="IsEquivalent" Style="Number"/>).
By the way, this called <C>CodeIsomorphism</C>.
For the current version of <Package>GUAVA</Package>, 
unless one of the codes is unrestricted,
this calls Leon's C program (which only works for binary linear codes
and only on a unix/linux computer). 

</Section>

<Section>
<Heading>
Operations for Codes
</Heading>
<Label Name="Operations for Codes"/>

<ManSection>
<Meth Name="\+" Label="for codes" Arg=" C1 C2"/>
		   
<Description>
<Index>
codes, addition
</Index>
<Index>
codes, direct sum
</Index>

The  operator `+' evaluates to the direct sum  of the codes <A>C1</A> and
<A>C2</A>.  See <Ref Func="DirectSumCode" Style="Number"/>.
<P/>

</Description>
</ManSection>
<Example>
gap> C1:=RandomLinearCode(10,5);
a  [10,5,?] randomly generated code over GF(2)
gap> C2:=RandomLinearCode(9,4);
a  [9,4,?] randomly generated code over GF(2)
gap> C1+C2;
a linear [10,9,1]0..10 unknown linear code over GF(2)
</Example>


<ManSection>
<Meth Name="\*" Label="for codes" Arg=" C1 C2"/>
		   
<Description>
<Index>
codes, product
</Index>

The operator `*'  evaluates to the direct product of the codes 
<A>C1</A> and <A>C2</A>. 
See <Ref Func="DirectProductCode" Style="Number"/>.
</Description>
</ManSection>

<Example>
gap> C1 := GeneratorMatCode( [ [1, 0,0,0], [0, 1,0,0] ], GF(2) );
a linear [4,2,1]1 code defined by generator matrix over GF(2)
gap> C2 := GeneratorMatCode( [ [0,0,1, 1], [0,0,0, 1] ], GF(2) );
a linear [4,2,1]1 code defined by generator matrix over GF(2)
gap> C1*C2;
a linear [16,4,1]4..12 direct product code
</Example>
<!--
C1 := GeneratorMatCode( [ [1, 0,0,0], [0, 1,0,0] ], GF(2) );
C2 := GeneratorMatCode( [ [0,0,1, 1], [0,0,0, 1] ], GF(2) );
C1*C2;
-->

<ManSection>
<Meth Name="\*" Label="for message and code" Arg=" m C"/>
		   
<Description>
<Index>codes, encoding </Index>
<Index>encoder map </Index>
The operator <C>m*C</C> evaluates to the element of 
<A>C</A> belonging to information word ('message') <A>m</A>. 
Here <A>m</A> may be a vector, polynomial, string or 
codeword or a list of those. 
This is the way to do encoding in 
<Package>GUAVA</Package>. <A>C</A> must be linear,
because in <Package>GUAVA</Package>,  
encoding by multiplication is only defined for
linear codes. If <A>C</A> is a cyclic code, this multiplication is the same as
multiplying an information polynomial <A>m</A> by the generator 
polynomial of <A>C</A>. 
If <A>C</A> is a linear code, it is equal to the multiplication 
of an information vector <A>m</A>  by
a generator matrix of <A>C</A>.
<P/>
To invert this, use the function <C>InformationWord</C> (see 
<Ref Func="InformationWord" Style="Number"/>,
which simply calls the function <C>Decode</C>).

</Description>
</ManSection>

<Example>
gap> C := GeneratorMatCode( [ [1, 0,0,0], [0, 1,0,0] ], GF(2) );
a linear [4,2,1]1 code defined by generator matrix over GF(2)
gap> m:=Codeword("11");
[ 1 1 ]
gap> m*C;
[ 1 1 0 0 ]
</Example>
<!--
C := GeneratorMatCode( [ [1, 0,0,0], [0, 1,0,0] ], GF(2) );
m:=Codeword("11");
m*C;
-->

<ManSection>
<Func Name="InformationWord" Arg=" C c"/>
		   
<Description>
<Index>codes, decoding </Index>
<Index>information bits </Index>
Here <A>C</A> is a linear code and <A>c</A> is 
a codeword in it. The command <C>InformationWord</C> 
returns the message word (or 'information digits') <M>m</M>
satisfying <C>c=m*C</C>. This command simply calls <C>Decode</C>, 
provided <C>c in C</C> is true. Otherwise, it returns an error. 
<P/>
To invert this, use the encoding function <C>*</C> (see 
<Ref Meth="\*" Label="for message and code" Style="Number"/>).

</Description>
</ManSection>

<Example>
gap> C:=HammingCode(3);
a linear [7,4,3]1 Hamming (3,2) code over GF(2)
gap> c:=Random(C);
[ 0 0 0 1 1 1 1 ]
gap> InformationWord(C,c);
[ 0 1 1 1 ]
gap> c:=Codeword("1111100");
[ 1 1 1 1 1 0 0 ]
gap> InformationWord(C,c);
"ERROR: codeword must belong to code"
gap> C:=NordstromRobinsonCode();
a (16,256,6)4 Nordstrom-Robinson code over GF(2)
gap> c:=Random(C);
[ 0 0 0 1 0 0 0 1 0 0 1 0 1 1 0 1 ]
gap> InformationWord(C,c);
"ERROR: code must be linear"
</Example>
<!--
C:=HammingCode(3);
c:=Random(C);
InformationWord(C,c);
c:=Codeword("1111100");
InformationWord(C,c);
C:=NordstromRobinsonCode();
c:=Random(C);
InformationWord(C,c);
-->


</Section>

<Section>
<Heading>
Boolean Functions for Codes
</Heading>
<Label Name="Boolean Functions for Codes"/>

<ManSection>
<Func Name="in" Arg=" c C"/>
		   
<Description>
<Index>code, element test</Index>
The command
<C>c in C</C> evaluates  to `true'  if  <A>C</A> contains the codeword or
list of codewords specified by <A>c</A>. 
Of course,  <A>c</A> and <A>C</A> must have the
same word lengths and base fields.
</Description>
</ManSection>

<Example>
gap> C:= HammingCode( 2 );; eC:= AsSSortedList( C );
[ [ 0 0 0 ], [ 1 1 1 ] ]
gap> eC[2] in C;
true
gap> [ 0 ] in C;
false 
</Example>
<!--
C:= HammingCode( 2 );; eC:= AsSSortedList( C );
eC[2] in C;
[ 0 ] in C;
-->

<ManSection>
<Func Name="IsSubset" Arg=" C1 C2"/>

<Description>
<Index>code, subcode</Index>
The command <C>IsSubset(C1,C2)</C> returns `true' if <A>C2</A> 
is a subcode of <A>C1</A>,
i.e.  if <A>C1</A> contains all the elements of <A>C2</A>.

</Description>
</ManSection>

<Example>
gap> IsSubset( HammingCode(3), RepetitionCode( 7 ) );
true
gap> IsSubset( RepetitionCode( 7 ), HammingCode( 3 ) );
false
gap> IsSubset( WholeSpaceCode( 7 ), HammingCode( 3 ) );
true
</Example>
<!--
IsSubset( HammingCode(3), RepetitionCode( 7 ) );
IsSubset( RepetitionCode( 7 ), HammingCode( 3 ) );
IsSubset( WholeSpaceCode( 7 ), HammingCode( 3 ) );
-->

<ManSection>
<Func Name="IsCode" Arg=" obj "/>

<Description>
<C>IsCode</C> returns `true'  if <A>obj</A>, which
can be an object of arbitrary type, is a code and 
`false' otherwise. Will cause an error if <A>obj</A> is an
unbound variable.
</Description>
</ManSection>

<Example>
gap> IsCode( 1 );
false
gap> IsCode( ReedMullerCode( 2,3 ) );
true
</Example>
<!--
IsCode( 1 );
IsCode( ReedMullerCode( 2,3 ) );
-->

<ManSection>
<Func Name="IsLinearCode" Arg=" obj "/>

<Description>
<C>IsLinearCode</C> checks if object <A>obj</A>  
(not necessarily a code) is a linear code. 
If a code has already been marked as linear or cyclic, the
function automatically returns `true'.  Otherwise, the function checks if
a basis <M>G</M>  of the elements of <A>obj</A>  exists that 
generates the elements
of <A>obj</A>. If so, <M>G</M> is recorded as
a generator matrix of <A>obj</A> and the function
returns `true'. If not, the function returns `false'.
</Description>
</ManSection>

<Example>
gap> C := ElementsCode( [ [0,0,0],[1,1,1] ], GF(2) );
a (3,2,1..3)1 user defined unrestricted code over GF(2)
gap> IsLinearCode( C );
true
gap> IsLinearCode( ElementsCode( [ [1,1,1] ], GF(2) ) );
false
gap> IsLinearCode( 1 );
false 
</Example>
<!--
C := ElementsCode( [ [0,0,0],[1,1,1] ], GF(2) );
IsLinearCode( C );
IsLinearCode( ElementsCode( [ [1,1,1] ], GF(2) ) );
IsLinearCode( 1 );
-->

<ManSection>
<Func Name="IsCyclicCode" Arg=" obj "/>

<Description>
<C>IsCyclicCode</C> checks if the object <A>obj</A> is a cyclic code. 
If a code has
already been marked as cyclic, the function automatically returns `true'.
Otherwise, the function checks if a polynomial <M>g</M> exists that generates
the elements of <A>obj</A>. If so, <M>g</M> is recorded as
a generator polynomial of 
<A>obj</A> and the function returns `true'. If not, the function 
returns `false'.
</Description>
</ManSection>

<Example>
gap> C := ElementsCode( [ [0,0,0], [1,1,1] ], GF(2) );
a (3,2,1..3)1 user defined unrestricted code over GF(2)
gap> # GUAVA does not know the code is cyclic
gap> IsCyclicCode( C );      # this command tells GUAVA to find out
true
gap> IsCyclicCode( HammingCode( 4, GF(2) ) );
false
gap> IsCyclicCode( 1 );
false 
</Example>
<!--
C := ElementsCode( [ [0,0,0], [1,1,1] ], GF(2) );
IsCyclicCode( C ); 
IsCyclicCode( HammingCode( 4, GF(2) ) );
IsCyclicCode( 1 );
-->

<ManSection>
<Func Name="IsPerfectCode" Arg=" C "/>

<Description>
<C>IsPerfectCode(C)</C> returns `true' if 
<A>C</A> is a perfect code. If <M>C\subset GF(q)^n</M>
then, by definition, this means that for some 
positive integer <M>t</M>, the space <M>GF(q)^n</M>
is covered by non-overlapping spheres of
(Hamming) radius <M>t</M> centered at the codewords in <A>C</A>.
For a code with odd minimum distance <M>d = 2t+1</M>, 
this is the case when every word of the
vector space of <A>C</A> is at distance at most <M>t</M> from exactly 
one element
of <A>C</A>. Codes with even minimum distance are never perfect.
<P/>
In  fact, a code that is not "trivially perfect" (the binary repetition
codes of odd length, the codes consisting of one word, and the codes
consisting of the  whole vector space), and does not have the parameters
of a Hamming or Golay code, cannot be perfect 
(see section 1.12 in <Cite Key="HP03"/>).
</Description>
</ManSection>
<Index>code, perfect</Index>

<Example>
gap> H := HammingCode(2);
a linear [3,1,3]1 Hamming (2,2) code over GF(2)
gap> IsPerfectCode( H );
true
gap> IsPerfectCode( ElementsCode([[1,1,0],[0,0,1]],GF(2)) );
true
gap> IsPerfectCode( ReedSolomonCode( 6, 3 ) );
false
gap> IsPerfectCode( BinaryGolayCode() );
true 
</Example>
<!--
H := HammingCode(2);
IsPerfectCode( H );
IsPerfectCode( ElementsCode([[1,1,0],[0,0,1]],GF(2)) );
IsPerfectCode( ReedSolomonCode( 6, 3 ) );
IsPerfectCode( BinaryGolayCode() );
-->

<ManSection>
<Func Name="IsMDSCode" Arg=" C "/>

<Description>
<C>IsMDSCode(C)</C> returns true if <A>C</A>  is a 
maximum distance separable (MDS) code. 
A linear <M>[n, k, d]</M>-code of length 
<M>n</M>, dimension <M>k</M> and minimum distance <M>d</M> 
is an MDS code  if <M>k=n-d+1</M>, in other words
if <A>C</A> meets the Singleton bound 
(see <Ref Func="UpperBoundSingleton" Style="Number"/>). An unrestricted 
<M>(n, M, d)</M> code is called <E>MDS</E> 
if <M>k=n-d+1</M>, with <M>k</M> equal
to the largest integer less than or equal 
to the logarithm of <M>M</M> with base
<M>q</M>, the size of the base field of <A>C</A>.
<P/>
Well-known MDS codes include the repetition codes, the whole space codes,
the even weight codes (these are the only <E>binary</E> MDS codes) and the
Reed-Solomon codes.
</Description>
</ManSection>
<Index>code, maximum distance separable</Index>
<Index>MDS</Index>

<Example>
gap> C1 := ReedSolomonCode( 6, 3 );
a cyclic [6,4,3]2 Reed-Solomon code over GF(7)
gap> IsMDSCode( C1 );
true    # 6-3+1 = 4
gap> IsMDSCode( QRCode( 23, GF(2) ) );
false 
</Example>
<!--
C1 := ReedSolomonCode( 6, 3 );
IsMDSCode( C1 );
IsMDSCode( QRCode( 23, GF(2) ) );
-->

<ManSection>
<Func Name="IsSelfDualCode" Arg=" C "/>

<Description>
<C>IsSelfDualCode(C)</C> returns `true' if <A>C</A> is self-dual, 
i.e. when <A>C</A> is equal to its dual code 
(see also <Ref Func="DualCode" Style="Number"/>). 
A code is self-dual if it contains 
all vectors that its elements are orthogonal to.
If a code is self-dual, it automatically 
is self-orthogonal (see 
<Ref Func="IsSelfOrthogonalCode" Style="Number"/>).
<P/>
If  <A>C</A> is a non-linear code, it cannot be self-dual
(the dual code is always linear), so `false' is
returned.  A linear code can only be self-dual when its 
dimension <M>k</M> is equal to the redundancy <M>r</M>.
</Description>
</ManSection>
<Index>code, self-dual</Index>

<Example>
gap> IsSelfDualCode( ExtendedBinaryGolayCode() );
true
gap> C := ReedMullerCode( 1, 3 );
a linear [8,4,4]2 Reed-Muller (1,3) code over GF(2)
gap> DualCode( C ) = C;
true 
</Example>

<Index>
self-orthogonal
</Index>

<ManSection>
<Func Name="IsSelfOrthogonalCode" Arg=" C "/>

<Description>
<C>IsSelfOrthogonalCode(C)</C> returns `true' if <A>C</A> 
is self-orthogonal. A code is <E>self-orthogonal</E> 
if every element of <A>C</A>  is orthogonal to all
elements of <A>C</A>, including itself. (In the linear case, this simply means
that the generator matrix of <A>C</A> multiplied with its transpose yields a
null matrix.)
</Description>
</ManSection>
<Index>code, self-orthogonal</Index>

<Example>
gap> R := ReedMullerCode(1,4);
a linear [16,5,8]6 Reed-Muller (1,4) code over GF(2)
gap> IsSelfOrthogonalCode(R);
true
gap> IsSelfDualCode(R);
false 
</Example>
<!--
R := ReedMullerCode(1,4);
IsSelfOrthogonalCode(R);
IsSelfDualCode(R);
-->

<Index>
doubly-even
</Index>

<ManSection>
	<Func Name="IsDoublyEvenCode" Arg=" C "/>
	
	<Description>
		<C>IsDoublyEvenCode(C)</C> returns `true' if <A>C</A> is
		a binary linear code which has codewords of weight divisible
		by 4 only. According to <Cite Key="HP03"/>, a doubly-even code
		is self-orthogonal and every row in its generator matrix has
		weight that is divisible by 4.
	</Description>
</ManSection>
<Index>code, doubly-even</Index>

<Example>
gap> C:=BinaryGolayCode();
a cyclic [23,12,7]3 binary Golay code over GF(2)
gap> WeightDistribution(C);
[ 1, 0, 0, 0, 0, 0, 0, 253, 506, 0, 0, 1288, 1288, 0, 0, 506, 253, 0, 0, 0, 0, 0, 0, 1 ]
gap> IsDoublyEvenCode(C);  
false
gap> C:=ExtendedCode(C);  
a linear [24,12,8]4 extended code
gap> WeightDistribution(C);
[ 1, 0, 0, 0, 0, 0, 0, 0, 759, 0, 0, 0, 2576, 0, 0, 0, 759, 0, 0, 0, 0, 0, 0, 0, 1 ]
gap> IsDoublyEvenCode(C);  
true
</Example>
<!--
C:=BinaryGolayCode();
WeightDistribution(C);
IsDoublyEvenCode(C);  
C:=ExtendedCode(C);  
WeightDistribution(C);
IsDoublyEvenCode(C);  
-->
	
<Index>
singly-even
</Index>

<ManSection>
	<Func Name="IsSinglyEvenCode" Arg=" C "/>
	
	<Description>
		<C>IsSinglyEvenCode(C)</C> returns `true' if <A>C</A> is
		a binary self-orthogonal linear code which is not doubly-even.
		In other words, <A>C</A> is a binary self-orthogonal code which
		has codewords of even weight.
	</Description>
</ManSection>
<Index>code, singly-even</Index>

<Example>
gap> x:=Indeterminate(GF(2));                     
x_1
gap> C:=QuasiCyclicCode( [x^0, 1+x^3+x^5+x^6+x^7], 11, GF(2) );
a linear [22,11,1..6]4..7 quasi-cyclic code over GF(2)
gap> IsSelfDualCode(C);  # self-dual is a restriction of self-orthogonal
true
gap> IsDoublyEvenCode(C);
false
gap> IsSinglyEvenCode(C);
true
</Example>
<!--
x:=Indeterminate(GF(2));
C:=QuasiCyclicCode( [x^0, 1+x^3+x^5+x^6+x^7], 11, GF(2) );
IsSelfDualCode(C);	# self-dual is a restriction of self-orthogonal
IsDoublyEvenCode(C);
IsSinglyEvenCode(C);
-->

<Index>
even
</Index>

<ManSection>
	<Func Name="IsEvenCode" Arg=" C "/>
	
	<Description>
		<C>IsEvenCode(C)</C> returns `true' if <A>C</A> is a binary
		linear code which has codewords of even weight--regardless
		whether or not it is self-orthogonal.
	</Description>
</ManSection>
<Index>code, even</Index>

<Example>
gap> C:=BinaryGolayCode();
a cyclic [23,12,7]3 binary Golay code over GF(2)
gap> IsSelfOrthogonalCode(C);
false
gap> IsEvenCode(C);
false
gap> C:=ExtendedCode(C);
a linear [24,12,8]4 extended code
gap> IsSelfOrthogonalCode(C);
true
gap> IsEvenCode(C);
true
gap> C:=ExtendedCode(QRCode(17,GF(2)));
a linear [18,9,6]3..5 extended code
gap> IsSelfOrthogonalCode(C);
false
gap> IsEvenCode(C);
true
</Example>
<!--
C:=BinaryGolayCode();
IsSelfOrthogonalCode(C);
IsEvenCode(C);
C:=ExtendedCode(C);
IsSelfOrthogonalCode(C);
IsEvenCode(C);
C:=ExtendedCode(QRCode(17,GF(2)));
IsSelfOrthogonalCode(C);
IsEvenCode(C);
-->

<Index>
self complementary code
</Index>

<ManSection>
<Func Name="IsSelfComplementaryCode" Arg=" C "/>

<Description>
<C>IsSelfComplementaryCode</C> returns `true' if

<Display>
v \in C \Rightarrow 1 - v \in C,
</Display>
where <M>1</M> is the all-one word of length <M>n</M>.
</Description>
</ManSection>

<Example>
gap> IsSelfComplementaryCode( HammingCode( 3, GF(2) ) );
true
gap> IsSelfComplementaryCode( EvenWeightSubcode(
> HammingCode( 3, GF(2) ) ) );
false 
</Example>

<Index>
affine code
</Index>

<ManSection>
<Func Name="IsAffineCode" Arg=" C "/>

<Description>
<C>IsAffineCode</C> returns `true' if <A>C</A> is an affine code.
A code is called <E>affine</E> if it is an affine space.
In other words, a code is affine if it is a coset of a linear code.
</Description>
</ManSection>

<Example>
gap> IsAffineCode( HammingCode( 3, GF(2) ) );
true
gap> IsAffineCode( CosetCode( HammingCode( 3, GF(2) ),
> [ 1, 0, 0, 0, 0, 0, 0 ] ) );
true
gap> IsAffineCode( NordstromRobinsonCode() );
false 
</Example>

<ManSection>
<Func Name="IsAlmostAffineCode" Arg=" C "/>

<Description>
<C>IsAlmostAffineCode</C> returns `true' if <A>C</A> 
is an almost affine code. A code is called <E>almost affine</E> 
if the size of any punctured code of <A>C</A> is <M>q^r</M> 
for some <M>r</M>, where <M>q</M> is the size of the alphabet
of the code.
Every affine code is also almost affine, and every code over 
<M>GF(2)</M> and <M>GF(3)</M> that is almost affine is also affine.
</Description>
</ManSection>

<Example>
gap> code := ElementsCode( [ [0,0,0], [0,1,1], [0,2,2], [0,3,3],
>                             [1,0,1], [1,1,0], [1,2,3], [1,3,2],
>                             [2,0,2], [2,1,3], [2,2,0], [2,3,1],
>                             [3,0,3], [3,1,2], [3,2,1], [3,3,0] ],
>                             GF(4) );;
gap> IsAlmostAffineCode( code );
true
gap> IsAlmostAffineCode( NordstromRobinsonCode() );
false 
</Example>
<!--
code := ElementsCode( [ [0,0,0], [0,1,1], [0,2,2], [0,3,3], [1,0,1], [1,1,0], [1,2,3], [1,3,2], [2,0,2], [2,1,3], [2,2,0], [2,3,1], [3,0,3], [3,1,2], [3,2,1], [3,3,0] ], GF(4) );;
IsAlmostAffineCode( code );
IsAlmostAffineCode( NordstromRobinsonCode() );
-->

</Section>

<Section>
<Heading>
Equivalence and Isomorphism of Codes
</Heading>
<Label Name="Equivalence and Isomorphism of Codes"/>

<Index>
permutation equivalent codes
</Index>
<Index>
equivalent codes
</Index>

<ManSection>
<Func Name="IsEquivalent" Arg=" C1 C2 "/>

<Description>
We say that 
<A>C1</A> is <E>permutation equivalent</E> to
<A>C2</A> if <A>C1</A> can be obtained from <A>C2</A> by
carrying out column permutations. 
<C>IsEquivalent</C> returns true if <A>C1</A> and 
<A>C2</A> are equivalent codes. 
At this time,
<C>IsEquivalent</C> only handles <E>binary</E> codes. 
(The external unix/linux program <B>desauto</B> from J. S. Leon 
is called by <C>IsEquivalent</C>.) 
Of course, if <A>C1</A> and <A>C2</A> are equal, they
are also equivalent.
<P/>
Note that the algorithm is <E>very slow</E> for non-linear codes.
<P/>
More generally, we say that 
<A>C1</A> is <E>equivalent</E> to
<A>C2</A> if <A>C1</A> can be obtained from <A>C2</A> by
carrying out column permutations and a permutation of the
alphabet. 
</Description>
</ManSection>

<Example>
gap> x:= Indeterminate( GF(2) );; pol:= x^3+x+1; 
Z(2)^0+x_1+x_1^3
gap> H := GeneratorPolCode( pol, 7, GF(2));          
a cyclic [7,4,1..3]1 code defined by generator polynomial over GF(2)
gap> H = HammingCode(3, GF(2));
false
gap> IsEquivalent(H, HammingCode(3, GF(2)));
true                        # H is equivalent to a Hamming code
gap> CodeIsomorphism(H, HammingCode(3, GF(2)));
(3,4)(5,6,7) 
</Example>
<!--
x:= Indeterminate( GF(2) );; pol:= x^3+x+1; 
H := GeneratorPolCode( pol, 7, GF(2));          
H = HammingCode(3, GF(2));
IsEquivalent(H, HammingCode(3, GF(2)));
CodeIsomorphism(H, HammingCode(3, GF(2)));
-->

<ManSection>
<Func Name="CodeIsomorphism" Arg=" C1 C2 "/>

<Description>
If the two codes <A>C1</A> and <A>C2</A> are permutation equivalent codes (see
<Ref Func="IsEquivalent" Style="Number"/>), 
<C>CodeIsomorphism</C> returns the permutation that
transforms <A>C1</A> into <A>C2</A>. If the codes are not equivalent,
it returns `false'. 
<P/>
At this time,
<C>IsEquivalent</C> only computes isomorphisms
between <E>binary</E> codes on a linux/unix computer 
(since it calls Leon's C program <B>desauto</B>).
</Description>
</ManSection>

<Example>
gap> x:= Indeterminate( GF(2) );; pol:= x^3+x+1; 
Z(2)^0+x_1+x_1^3
gap> H := GeneratorPolCode( pol, 7, GF(2));          
a cyclic [7,4,1..3]1 code defined by generator polynomial over GF(2)
gap> CodeIsomorphism(H, HammingCode(3, GF(2)));
(3,4)(5,6,7) 
gap> PermutedCode(H, (3,4)(5,6,7)) = HammingCode(3, GF(2));
true 
</Example>
<!--
x:= Indeterminate( GF(2) );; pol:= x^3+x+1; 
H := GeneratorPolCode( pol, 7, GF(2));          
CodeIsomorphism(H, HammingCode(3, GF(2)));
PermutedCode(H, (3,4)(5,6,7)) = HammingCode(3, GF(2));
-->

<ManSection>
<Func Name="AutomorphismGroup" Arg=" C "/>

<Description>
<C>AutomorphismGroup</C> returns the automorphism group of a 
linear code <A>C</A>. For a binary code,
the automorphism group is the largest permutation group 
of degree <M>n</M> such that each permutation applied to 
the columns of <A>C</A> again yields <A>C</A>. 
<Package>GUAVA</Package> calls the external program 
<B>desauto</B> written by J. S. Leon, if it exists, to compute the 
automorphism group. If Leon's program is not compiled on the
system (and in the default directory) then it calls instead the
much slower program <C>PermutationAutomorphismGroup</C>.
<P/>
See Leon <Cite Key="Leon82"/> for a more precise description of the 
method, and the <File>guava/src/leon/doc</File> subdirectory for 
for details about Leon's C programs.
<P/>
The function <C>PermutedCode</C> 
permutes the columns of a code (see 
<Ref Func="PermutedCode" Style="Number"/>).
</Description>
</ManSection>

<Example>
gap> R := RepetitionCode(7,GF(2));
a cyclic [7,1,7]3 repetition code over GF(2)
gap> AutomorphismGroup(R);
Sym( [ 1 .. 7 ] )
                        # every permutation keeps R identical
gap> C := CordaroWagnerCode(7);
a linear [7,2,4]3 Cordaro-Wagner code over GF(2)
gap> AsSSortedList(C);
[ [ 0 0 0 0 0 0 0 ], [ 0 0 1 1 1 1 1 ], [ 1 1 0 0 0 1 1 ], [ 1 1 1 1 1 0 0 ] ]
gap> AutomorphismGroup(C);
Group([ (3,4), (4,5), (1,6)(2,7), (1,2), (6,7) ])
gap> C2 :=  PermutedCode(C, (1,6)(2,7));
a linear [7,2,4]3 permuted code
gap> AsSSortedList(C2);
[ [ 0 0 0 0 0 0 0 ], [ 0 0 1 1 1 1 1 ], [ 1 1 0 0 0 1 1 ], [ 1 1 1 1 1 0 0 ] ]
gap> C2 = C;
true 
</Example>
<!--
R := RepetitionCode(7,GF(2));
AutomorphismGroup(R);
C := CordaroWagnerCode(7);
AsSSortedList(C);
AutomorphismGroup(C);
C2 :=  PermutedCode(C, (1,6)(2,7));
AsSSortedList(C2);
C2 = C;
-->

<Index>PermutationAutomorphismGroup</Index>

<ManSection>
<Func Name="PermutationAutomorphismGroup" Arg=" C "/>

<Description>
<C>PermutationAutomorphismGroup</C> returns the permutation automorphism group  
of a linear code <A>C</A>. This is the largest permutation group of 
degree <M>n</M> such that each permutation applied to the 
columns of <A>C</A> again yields <A>C</A>.
It is written in GAP, so is much slower than
<C>AutomorphismGroup</C>. 
<P/>
When <A>C</A> is binary <C>PermutationAutomorphismGroup</C> does <E>not</E> call
<C>AutomorphismGroup</C>, even though they agree mathematically
in that case. This way <C>PermutationAutomorphismGroup</C> can be
called on any platform which runs GAP.
<P/>
The older name for this command,
<C>PermutationGroup</C>, will become obsolete in the next version of GAP.

</Description>
</ManSection>

<Example>
gap> R := RepetitionCode(3,GF(3));
a cyclic [3,1,3]2 repetition code over GF(3)
gap> G:=PermutationAutomorphismGroup(R);
Group([ (), (1,3), (1,2,3), (2,3), (1,3,2), (1,2) ])
gap> G=SymmetricGroup(3);
true
</Example>
<!--
R := RepetitionCode(3,GF(3));
G:=PermutationAutomorphismGroup(R);
G=SymmetricGroup(3);
-->

</Section>

<Section>
<Heading>
Domain Functions for Codes
</Heading>
<Label Name="Domain Functions for Codes"/>


These are some GAP functions that work on `Domains' in general. 
Their specific effect on `Codes' is explained here.

<ManSection>
<Func Name="IsFinite" Arg=" C "/>

<Description>
<C>IsFinite</C> is an implementation of the GAP 
domain function <C>IsFinite</C>. It returns true for a 
code <A>C</A>.
</Description>
</ManSection>

<Example>
gap> IsFinite( RepetitionCode( 1000, GF(11) ) );
true 
</Example>

<ManSection>
<Func Name="Size" Arg=" C "/>

<Description>
<C>Size</C> returns the size of <A>C</A>, the number of elements 
of the code. If the code is linear, the size of the code 
is equal to <M>q^k</M>, where <M>q</M> is
the size of the base field of <A>C</A> and <M>k</M> 
is the dimension.
</Description>
</ManSection>

<Example>
gap> Size( RepetitionCode( 1000, GF(11) ) );
11
gap> Size( NordstromRobinsonCode() );
256 
</Example>

<ManSection>
<Func Name="LeftActingDomain" Arg=" C "/>

<Description>
<C>LeftActingDomain</C> returns the base field of
a code <A>C</A>. Each element of <A>C</A>
consists  of elements of this base  field. 
If the base field is <M>F</M>, and the word length 
of the code is <M>n</M>, then the codewords are elements of
<M>F^n</M>. 
If <A>C</A> is a cyclic code, its elements are interpreted
as polynomials with coefficients over <M>F</M>.
</Description>
</ManSection>

<Example>
gap> C1 := ElementsCode([[0,0,0], [1,0,1], [0,1,0]], GF(4));
a (3,3,1..3)2..3 user defined unrestricted code over GF(4)
gap> LeftActingDomain( C1 );
GF(2^2)
gap> LeftActingDomain( HammingCode( 3, GF(9) ) );
GF(3^2) 
</Example>

<ManSection>
<Func Name="Dimension" Arg=" C "/>

<Description>
<C>Dimension</C> returns the parameter <M>k</M> of <A>C</A>, 
the dimension of the code, or the number of information 
symbols in each codeword. The dimension is
not defined for non-linear codes; 
<C>Dimension</C> then returns an error.
</Description>
</ManSection>

<Example>
gap> Dimension( NullCode( 5, GF(5) ) );
0
gap> C := BCHCode( 15, 4, GF(4) );
a cyclic [15,9,5]3..4 BCH code, delta=5, b=1 over GF(4)
gap> Dimension( C );
9
gap> Size( C ) = Size( LeftActingDomain( C ) ) ^ Dimension( C );
true 
</Example>
<!--
Dimension( NullCode( 5, GF(5) ) );
C := BCHCode( 15, 4, GF(4) );
Dimension( C );
Size( C ) = Size( LeftActingDomain( C ) ) ^ Dimension( C );
-->

<ManSection>
<Func Name="AsSSortedList" Arg=" C "/>

<Description>
<C>AsSSortedList</C> (as strictly sorted list) returns an
immutable, duplicate free list of the elements of 
<A>C</A>. For a finite field <M>GF(q)</M> generated by powers
of <M>Z(q)</M>, the ordering on 
<Display>
GF(q)=\{ 0 , Z(q)^0, Z(q), Z(q)^2, ...Z(q)^{q-2} \} 
</Display>
is that determined by the exponents <M>i</M>.  
These elements are of the type codeword 
(see <Ref Func="Codeword" Style="Number"/>). Note that for large codes,
generating the elements may be very time- and memory-consuming. 
For generating a specific element or a subset of the elements,  
use <C>CodewordNr</C> (see 
<Ref Func="CodewordNr" Style="Number"/>).
</Description>
</ManSection>

<Example>
gap> C := ConferenceCode( 5 );
a (5,12,2)1..4 conference code over GF(2)
gap> AsSSortedList( C );
[ [ 0 0 0 0 0 ], [ 0 0 1 1 1 ], [ 0 1 0 1 1 ], [ 0 1 1 0 1 ], [ 0 1 1 1 0 ], 
  [ 1 0 0 1 1 ], [ 1 0 1 0 1 ], [ 1 0 1 1 0 ], [ 1 1 0 0 1 ], [ 1 1 0 1 0 ], 
  [ 1 1 1 0 0 ], [ 1 1 1 1 1 ] ]
gap> CodewordNr( C, [ 1, 2 ] );
[ [ 0 0 0 0 0 ], [ 0 0 1 1 1 ] ]
</Example>
<!--
C := ConferenceCode( 5 );
AsSSortedList( C );
CodewordNr( C, [ 1, 2 ] );
-->

</Section>


<Section>
<Heading>
Printing and Displaying Codes
</Heading>
<Label Name="Printing and Displaying Codes"/>


<ManSection>
<Func Name="Print" Arg=" C "/>

<Description>
<C>Print</C> prints information about <A>C</A>. This is the same as typing
the identifier <A>C</A> at the GAP-prompt.
<P/>
If the argument is an unrestricted code, information in the form

<Verb>
a (n,M,d)r ... code over GF(q)
</Verb>
is printed, where <A>n</A> is the word length, <A>M</A> 
the number of elements of the code, <A>d</A> the minimum distance 
and <A>r</A> the covering radius.
<P/>
If the argument is a linear code, information in the form

<Verb>
a linear [n,k,d]r ... code over GF(q)
</Verb>
is printed, where <A>n</A> is the word length, <A>k</A> 
the dimension of the code, <A>d</A> the minimum distance 
and <A>r</A> the covering radius.
<P/>
Except for codes produced by <C>RandomLinearCode</C>, 
if <A>d</A> is not yet known, it is displayed in the form

<Verb>
lowerbound..upperbound
</Verb>
and if <A>r</A> is not yet known, it is displayed in the same way.
For certain ranges of <M>n</M>, the values of
<A>lowerbound</A> and <A>upperbound</A> are obtained from tables.
<P/>
The function <C>Display</C> gives more information. 
See 
<Ref Func="Display" Style="Number"/>.
</Description>
</ManSection>

<Example>
gap> C1 := ExtendedCode( HammingCode( 3, GF(2) ) );
a linear [8,4,4]2 extended code
gap> Print( "This is ", NordstromRobinsonCode(), ". \n");
This is a (16,256,6)4 Nordstrom-Robinson code over GF(2). 
</Example>

<ManSection>
<Func Name="String" Arg=" C "/>

<Description>
<C>String</C> returns information about <A>C</A> in a string. 
This function is used by <C>Print</C>.
</Description>
</ManSection>

<Example>
gap> x:= Indeterminate( GF(3) );; pol:= x^2+1;
x_1^2+Z(3)^0
gap> Factors(pol);
[ x_1^2+Z(3)^0 ]
gap> H := GeneratorPolCode( pol, 8, GF(3));
a cyclic [8,6,1..2]1..2 code defined by generator polynomial over GF(3)
gap> String(H);
"a cyclic [8,6,1..2]1..2 code defined by generator polynomial over GF(3)"
</Example>
<!--
x:= Indeterminate( GF(3) );; pol:= x^2+1;
Factors(pol);
H := GeneratorPolCode( pol, 8, GF(3));
String(H);
-->

<ManSection>
<Func Name="Display" Arg=" C "/>

<Description>
<C>Display</C> prints the method of construction of code <A>C</A>. 
With this history, in most cases an equal or equivalent code can be
reconstructed. If <A>C</A> is an unmanipulated code, the result 
is equal to output of the function <C>Print</C> (see 
<Ref Func="Print" Style="Number"/>).
</Description>
</ManSection>

<Example>
gap> Display( RepetitionCode( 6, GF(3) ) );
a cyclic [6,1,6]4 repetition code over GF(3)
gap> C1 := ExtendedCode( HammingCode(2) );;
gap> C2 := PuncturedCode( ReedMullerCode( 2, 3 ) );;
gap> Display( LengthenedCode( UUVCode( C1, C2 ) ) );
a linear [12,8,2]2..4 code, lengthened with 1 column(s) of
a linear [11,8,1]1..2 U U+V construction code of
U: a linear [4,1,4]2 extended code of
   a linear [3,1,3]1 Hamming (2,2) code over GF(2)
V: a linear [7,7,1]0 punctured code of
   a cyclic [8,7,2]1 Reed-Muller (2,3) code over GF(2)
</Example>
<!--
Display( RepetitionCode( 6, GF(3) ) );
C1 := ExtendedCode( HammingCode(2) );;
C2 := PuncturedCode( ReedMullerCode( 2, 3 ) );;
Display( LengthenedCode( UUVCode( C1, C2 ) ) );
-->

<ManSection>
<Func Name="DisplayBoundsInfo" Arg=" bds "/>

<Description>
<C>DisplayBoundsInfo</C> prints the method of construction of 
the code <M>C</M> indicated in <C>bds:= BoundsMinimumDistance( n, k, GF(q) )</C>. 
</Description>
</ManSection>

<Example>
gap> bounds := BoundsMinimumDistance( 20, 17, GF(4) );
gap> DisplayBoundsInfo(bounds);
an optimal linear [20,17,d] code over GF(4) has d=3
--------------------------------------------------------------------------------------------------
Lb(20,17)=3, by shortening of:
Lb(21,18)=3, by applying contruction B to a [81,77,3] code
Lb(81,77)=3, by shortening of:
Lb(85,81)=3, reference: Ham
--------------------------------------------------------------------------------------------------
Ub(20,17)=3, by considering shortening to:
Ub(7,4)=3, by considering puncturing to:
Ub(6,4)=2, by construction B applied to:
Ub(2,1)=2, repetition code
--------------------------------------------------------------------------------------------------
Reference Ham:
%T this reference is unknown, for more info
%T contact A.E. Brouwer (aeb@cwi.nl)
</Example>
<!--
bounds := BoundsMinimumDistance( 20, 17, GF(4) );
DisplayBoundsInfo(bounds);
-->


</Section>

<Section>
<Heading>
Generating (Check) Matrices and Polynomials
</Heading>
<Label Name="Generating (Check) Matrices and Polynomials"/>

<ManSection>
<Func Name="GeneratorMat" Arg=" C "/>

<Description>
<C>GeneratorMat</C> returns a generator matrix of <A>C</A>. 
The code consists of all linear combinations of the rows of this matrix.
<P/>
If until now  no generator matrix of <A>C</A> was determined, 
it is computed from either the parity check matrix, the 
generator polynomial, the check polynomial or the elements 
(if possible), whichever is available.
<P/>
If <A>C</A> is a non-linear code, the function returns an error.
</Description>
</ManSection>

<Example>
gap> GeneratorMat( HammingCode( 3, GF(2) ) );
[ [ an immutable GF2 vector of length 7], 
  [ an immutable GF2 vector of length 7], 
  [ an immutable GF2 vector of length 7], 
  [ an immutable GF2 vector of length 7] ]
gap> Display(last);
 1 1 1 . . . .
 1 . . 1 1 . .
 . 1 . 1 . 1 .
 1 1 . 1 . . 1
gap> GeneratorMat( RepetitionCode( 5, GF(25) ) );
[ [ Z(5)^0, Z(5)^0, Z(5)^0, Z(5)^0, Z(5)^0 ] ]
gap> GeneratorMat( NullCode( 14, GF(4) ) );
[  ]
</Example>
<!--
GeneratorMat( HammingCode( 3, GF(2) ) );
Display(last);
GeneratorMat( RepetitionCode( 5, GF(25) ) );
GeneratorMat( NullCode( 14, GF(4) ) );
-->

<ManSection>
<Func Name="CheckMat" Arg=" C "/>

<Description>
<C>CheckMat</C> returns a parity check matrix of <A>C</A>. 
The code consists of all
words orthogonal to each of the rows of this matrix. The transpose of the
matrix is a right inverse of the generator  matrix. The parity check
matrix is computed from either the generator matrix, the generator
polynomial, the check polynomial or the elements  of <A>C</A> (if possible),
whichever is available.
<P/>
If <A>C</A> is a non-linear code, the function returns an error.
</Description>
</ManSection>

<Example>
gap> CheckMat( HammingCode(3, GF(2) ) );
[ [ 0*Z(2), 0*Z(2), 0*Z(2), Z(2)^0, Z(2)^0, Z(2)^0, Z(2)^0 ], 
  [ 0*Z(2), Z(2)^0, Z(2)^0, 0*Z(2), 0*Z(2), Z(2)^0, Z(2)^0 ],
  [ Z(2)^0, 0*Z(2), Z(2)^0, 0*Z(2), Z(2)^0, 0*Z(2), Z(2)^0 ] ]
gap> Display(last);
 . . . 1 1 1 1
 . 1 1 . . 1 1
 1 . 1 . 1 . 1
gap> CheckMat( RepetitionCode( 5, GF(25) ) );
[ [ Z(5)^0, Z(5)^2, 0*Z(5), 0*Z(5), 0*Z(5) ],
  [ 0*Z(5), Z(5)^0, Z(5)^2, 0*Z(5), 0*Z(5) ],
  [ 0*Z(5), 0*Z(5), Z(5)^0, Z(5)^2, 0*Z(5) ],
  [ 0*Z(5), 0*Z(5), 0*Z(5), Z(5)^0, Z(5)^2 ] ]
gap> CheckMat( WholeSpaceCode( 12, GF(4) ) );
[  ] 
</Example>
<!--
CheckMat( HammingCode(3, GF(2) ) );
Display(last);
CheckMat( RepetitionCode( 5, GF(25) ) );
CheckMat( WholeSpaceCode( 12, GF(4) ) );
-->

<ManSection>
<Func Name="GeneratorPol" Arg=" C "/>

<Description>
<C>GeneratorPol</C> returns the generator polynomial of <A>C</A>. 
The code consists of all multiples of the generator polynomial 
modulo <M>x^{n}-1</M>, where <M>n</M>
is the word  length of <A>C</A>.  
The generator polynomial is determined from either the check 
polynomial, the generator or check matrix or the
elements of <A>C</A> (if possible), whichever is available.
<P/>
If <A>C</A> is not a cyclic code, the function returns `false'.
</Description>
</ManSection>

<Example>
gap> GeneratorPol(GeneratorMatCode([[1, 1, 0], [0, 1, 1]], GF(2)));
Z(2)^0+x_1
gap> GeneratorPol( WholeSpaceCode( 4, GF(2) ) );
Z(2)^0
gap> GeneratorPol( NullCode( 7, GF(3) ) );
-Z(3)^0+x_1^7
</Example>
<!--
GeneratorPol(GeneratorMatCode([[1, 1, 0], [0, 1, 1]], GF(2)));
GeneratorPol( WholeSpaceCode( 4, GF(2) ) );
GeneratorPol( NullCode( 7, GF(3) ) );
-->

<ManSection>
<Func Name="CheckPol" Arg=" C "/>

<Description>
<C>CheckPol</C> returns the check polynomial of 
<A>C</A>. The code consists of all polynomials <M>f</M> 
with 
<Display>
f\cdot h \equiv 0 \ ({\rm mod}\  x^n-1),
</Display>
where <M>h</M> is the check polynomial, and <M>n</M> is the 
word length of <A>C</A>. The check polynomial is
computed  from the generator polynomial, the generator or parity check
matrix or the elements of <A>C</A> (if possible), whichever is available.
<P/>
If <A>C</A> if not a cyclic code, the function returns an error.
</Description>
</ManSection>

<Example>
gap> CheckPol(GeneratorMatCode([[1, 1, 0], [0, 1, 1]], GF(2)));
Z(2)^0+x_1+x_1^2
gap> CheckPol(WholeSpaceCode(4, GF(2)));
Z(2)^0+x_1^4
gap> CheckPol(NullCode(7,GF(3)));
Z(3)^0
</Example>
<!--
CheckPol(GeneratorMatCode([[1, 1, 0], [0, 1, 1]], GF(2)));
CheckPol(WholeSpaceCode(4, GF(2)));
CheckPol(NullCode(7,GF(3)));
-->

<ManSection>
<Func Name="RootsOfCode" Arg=" C "/>

<Description>
<C>RootsOfCode</C> returns a list of all zeros of the generator polynomial of
a cyclic code <A>C</A>. These are finite field elements in the splitting field
of the generator  polynomial, <M>GF(q^m)</M>, <M>m</M> 
is the multiplicative order
of the size of the base field of the code, modulo the word length.
<P/>
The reverse  process, constructing  a code from  a set  of roots,  can  be
carried out by the function <C>RootsCode</C> (see 
<Ref Func="RootsCode" Style="Number"/>).
</Description>
</ManSection>

<Example>
gap> C1 := ReedSolomonCode( 16, 5 );
a cyclic [16,12,5]3..4 Reed-Solomon code over GF(17)
gap> RootsOfCode( C1 );
[ Z(17), Z(17)^2, Z(17)^3, Z(17)^4 ]
gap> C2 := RootsCode( 16, last );
a cyclic [16,12,5]3..4 code defined by roots over GF(17)
gap> C1 = C2;
true 
</Example>
<!--
C1 := ReedSolomonCode( 16, 5 );
RootsOfCode( C1 );
C2 := RootsCode( 16, last );
C1 = C2;
-->

</Section>


<Section>
<Heading>
Parameters of Codes
</Heading>
<Label Name="Parameters of Codes"/>

<ManSection>
<Func Name="WordLength" Arg=" C "/>

<Description>
<C>WordLength</C> returns the parameter <M>n</M> of  
<A>C</A>, the word length of the elements. Elements of 
cyclic codes are polynomials of maximum degree
<M>n-1</M>, as calculations are carried out modulo 
<M>x^{n}-1</M>.

</Description>
</ManSection>

<Example>
gap> WordLength( NordstromRobinsonCode() );
16
gap> WordLength( PuncturedCode( WholeSpaceCode(7) ) );
6
gap> WordLength( UUVCode( WholeSpaceCode(7), RepetitionCode(7) ) );
14 
</Example>
<!--
WordLength( NordstromRobinsonCode() );
WordLength( PuncturedCode( WholeSpaceCode(7) ) );
WordLength( UUVCode( WholeSpaceCode(7), RepetitionCode(7) ) );
-->

<ManSection>
<Func Name="Redundancy" Arg=" C "/>

<Description>
<C>Redundancy</C> returns the redundancy 
<M>r</M> of <A>C</A>, which is equal to the
number of check symbols in each element. 
If <A>C</A> is not a linear code the redundancy is 
not defined and <C>Redundancy</C> returns an error.
<P/>
If a linear code <A>C</A> has dimension <M>k</M> and
word length  <M>n</M>, it has redundancy <M>r=n-k</M>.

</Description>
</ManSection>

<Example>
gap> C := TernaryGolayCode();
a cyclic [11,6,5]2 ternary Golay code over GF(3)
gap> Redundancy(C);
5
gap> Redundancy( DualCode(C) );
6 
</Example>
<!--
C := TernaryGolayCode();
Redundancy(C);
Redundancy( DualCode(C) );
-->

<ManSection>
<Func Name="MinimumDistance" Arg=" C "/>

<Description>
<C>MinimumDistance</C> returns the minimum distance 
of <A>C</A>, the largest integer <M>d</M> with the 
property that every element of <A>C</A> has at least a
Hamming  distance <M>d</M> (see 
<Ref Func="DistanceCodeword" Style="Number"/>) 
to any other element of <A>C</A>.  
For linear codes, the minimum distance is equal to the minimum
weight. This means that <M>d</M> is also the 
smallest positive value with <M>w[d+1] \neq 0</M>, where 
<M>w=(w[1],w[2],...,w[n])</M> is the weight distribution 
of  <A>C</A> (see 
<Ref Func="WeightDistribution" Style="Number"/>). For unrestricted codes, 
<M>d</M> is the smallest positive value with <M>w[d+1] \neq 0</M>, 
where <M>w</M>  is the inner distribution
of <A>C</A> (see 
<Ref Func="InnerDistribution" Style="Number"/>).
<P/>
For  codes with only  one element, the  minimum distance is defined to be
equal to the word length.
<P/>
For linear codes <A>C</A>, the algorithm used is the following:
After replacing <A>C</A> by a permutation equivalent <A>C'</A>, 
one may assume the generator matrix has the following form
<M>G=(I_{k} \, | \, A)</M>, for some <M>k\times (n-k)</M> 
matrix <M>A</M>. If <M>A=0</M> then return <M>d(C)=1</M>.
Next, find the minimum distance of the code spanned by the 
rows of <M>A</M>. Call this distance <M>d(A)</M>. 
Note that <M>d(A)</M> is equal to the 
the Hamming distance <M>d(v,0)</M> where <M>v</M> 
is some proper linear combination of <M>i</M> 
distinct rows of <M>A</M>.
Return <M>d(C)=d(A)+i</M>, where <M>i</M> is as in the previous step.
<P/>
This command may also be called using the syntax
<C>MinimumDistance(C, w)</C>.
In  this  form, <C>MinimumDistance</C> returns the 
minimum distance of a codeword <A>w</A> to the code <A>C</A>,
also called the <E>distance from <A>w</A> to</E> <A>C</A>. This is
the smallest value <M>d</M> for which there is an element 
<M>c</M>  of the code <A>C</A> which is at distance <M>d</M> from 
<A>w</A>. So <M>d</M> is also the minimum value for
which <M>D[d+1] \neq  0</M>, where <M>D</M> is 
the distance distribution of <A>w</A> to <A>C</A> 
(see <Ref Func="DistancesDistribution" Style="Number"/>).
<P/>
Note that <A>w</A> must be an element of the same vector space 
as the elements of <A>C</A>.  
<A>w</A> does not necessarily belong to the code (if it does, the
minimum distance is zero).
</Description>
</ManSection>

<Example>
gap> C := MOLSCode(7);; MinimumDistance(C);
3
gap> WeightDistribution(C);
[ 1, 0, 0, 24, 24 ]
gap> MinimumDistance( WholeSpaceCode( 5, GF(3) ) );
1
gap> MinimumDistance( NullCode( 4, GF(2) ) );
4
gap> C := ConferenceCode(9);; MinimumDistance(C);
4
gap> InnerDistribution(C);
[ 1, 0, 0, 0, 63/5, 9/5, 18/5, 0, 9/10, 1/10 ] 
gap> C := MOLSCode(7);; w := CodewordNr( C, 17 );
[ 3 3 6 2 ]
gap> MinimumDistance( C, w );
0
gap> C := RemovedElementsCode( C, w );; MinimumDistance( C, w );
3                           # so w no longer belongs to C 
</Example>
<!--
C := MOLSCode(7);; MinimumDistance(C);
WeightDistribution(C);
MinimumDistance( WholeSpaceCode( 5, GF(3) ) );
MinimumDistance( NullCode( 4, GF(2) ) );
C := ConferenceCode(9);; MinimumDistance(C);
InnerDistribution(C);
C := MOLSCode(7);; w := CodewordNr( C, 17 );
MinimumDistance( C, w );
C := RemovedElementsCode( C, w );; MinimumDistance( C, w );
-->

See also the <Package>GUAVA</Package>  
commands relating to bounds on the
minimum distance in section
<Ref Label="Distance bounds on codes" Style="Number"/>.

<ManSection>
<Func Name="MinimumDistanceLeon" Arg=" C "/>

<Description>
<C>MinimumDistanceLeon</C> returns the ``probable'' minimum distance 
<M>d_{Leon}</M> of a linear binary code <A>C</A>, using an implementation of 
Leon's probabilistic polynomial time algorithm. Briefly:
Let <A>C</A> be a linear code of dimension <M>k</M> over 
<M>GF(q)</M> as above. The algorithm has input parameters <M>s</M> and <M>\rho</M>,
where <M>s</M> is an integer between <M>2</M> and <M>n-k</M>, and 
<M>\rho</M> is an integer between <M>2</M> and <M>k</M>.

<List>
<Item>  
Find a generator matrix <M>G</M> of <M>C</M>.
</Item>

<Item>
Randomly permute the columns of <M>G</M>.
</Item>

<Item>
Perform Gaussian elimination on the permuted matrix to obtain a
new matrix of the following form: 
<Display>
G=(I_{k} \, | \, Z \, | \, B)
</Display>
with <M>Z</M> a <M>k\times s</M> matrix. If <M>(Z,B)</M> is the
zero matrix then return <M>1</M> for the minimum distance.
If <M>Z=0</M> but not <M>B</M> then either choose another 
permutation of the rows of <A>C</A> or return `method fails'. 
</Item>

<Item>
Search <M>Z</M> for at most <M>\rho</M> rows that lead to codewords of
weight less than <M>\rho</M>.
</Item>

<Item>
For these codewords, compute the weight of the whole word in <A>C</A>.
Return this weight.
</Item>
</List>
(See for example J. S. Leon, <Cite Key="Leon88"/> for more details.)
Sometimes (as is the case in <Package>GUAVA</Package>) 
this probabilistic algorithm 
is repeated several times and the most commonly occurring value
is taken. (This function actually has two optional
arguments: <C>p</C> and <C>num</C>. The command
<C>MinimumDistanceLeon(C,p,num)</C> allows a bit more
flexibility for the user - see the GAP code in codeops.gi for details.)
</Description>
</ManSection>

<Example>
gap> C:=RandomLinearCode(50,22,GF(2));
a  [50,22,?] randomly generated code over GF(2)
gap> MinimumDistanceLeon(C); time;
6
211
gap> MinimumDistance(C); time;
6
1204
</Example>
<!--
C:=RandomLinearCode(50,22,GF(2));
MinimumDistanceLeon(C); time;
MinimumDistance(C); time;
-->

<ManSection>
	<Func Name="MinimumWeight" Arg=" C "/>

	<Description>
		<C>MinimumWeight</C> returns the minimum Hamming weight of a linear
		code <A>C</A>. At the moment, this function works for binary and
		ternary codes only. The <C>MinimumWeight</C> function relies on
		an external executable program which is written in C language. As
		a consequence, the execution time of <C>MinimumWeight</C> function
		is faster than that of <Ref Func="MinimumDistance" Style="Number"/>
		function.
		<P/>
		The <C>MinimumWeight</C> function implements Chen's <Cite Key="Chen69"/> algorithm
		if <A>C</A> is cyclic, and Zimmermann's <Cite Key="Zimmermann96"/> algorithm
		if <A>C</A> is a general linear code. This function has a built-in check on
		the constraints of the minimum weight codewords. For example, for a self-orthogonal
		code over GF(3), the minimum weight codewords have weight that is divisible by
		3, i.e. 0 mod 3 congruence. Similary, self-orthogonal codes over GF(2) have
		codeword weights that are divisible by 4 and even codes over GF(2) have codewords
		weights that are divisible by 2. By taking these constraints into account, in many
		cases, the execution time may be significantly reduced. Consider the minimum
		Hamming weight enumeration of the <M>[151,45]</M> binary cyclic code (second
		example below). This cyclic code is self-orthogonal, so the weight of all
		codewords is divisible by 4. Without considering this constraint, the computation
		will finish at information weight <M>10</M>, rather than <M>9</M>. We can see
		that, this 0 mod 4 constraint on the codeword weights, has allowed us to avoid
		enumeration of <M>b(45,10) = 3,190,187,286</M> additional codewords, where
		<M>b(n,k)=n!/((n-k)!k!)</M> is the binomial coefficient of integers <M>n</M>
		and <M>k</M>.
		<P/>
		Note that the C source code for this minimum weight computation has not yet
	    been optimised, especially the code for GF(3), and there are chances to improve
		the speed of this function. Your contributions are most welcomed.
		<P/>
		If you find any bugs on this function, please report it to ctjhai@plymouth.ac.uk.
	</Description>
</ManSection>

<Example>
gap> # Extended ternary quadratic residue code of length 48
gap> n := 47;;
gap> x := Indeterminate(GF(3));;
gap> F := Factors(x^n-1);;
gap> v := List([1..n], i->Zero(GF(3)));;
gap> v := v + MutableCopyMat(VectorCodeword( Codeword(F[2]) ));;
gap> G := CirculantMatrix(24, v);;
gap> for i in [1..Size(G)] do; s:=Zero(GF(3));
> for j in [1..Size(G[i])] do; s:=s+G[i][j]; od; Append(G[i], [ s ]);
> od;;
gap> C := GeneratorMatCodeNC(G, GF(3));
a  [48,24,?] randomly generated code over GF(3)
gap> MinimumWeight(C);
[48,24] linear code over GF(3) - minimum weight evaluation
Known lower-bound: 1
There are 2 generator matrices, ranks : 24 24 
The weight of the minimum weight codeword satisfies 0 mod 3 congruence
Enumerating codewords with information weight 1 (w=1)
    Found new minimum weight 15
Number of matrices required for codeword enumeration 2
Completed w= 1, 48 codewords enumerated, lower-bound 6, upper-bound 15
Termination expected with information weight 6 at matrix 1
-----------------------------------------------------------------------------
Enumerating codewords with information weight 2 (w=2) using 2 matrices
Completed w= 2, 1104 codewords enumerated, lower-bound 6, upper-bound 15
Termination expected with information weight 6 at matrix 1
-----------------------------------------------------------------------------
Enumerating codewords with information weight 3 (w=3) using 2 matrices
Completed w= 3, 16192 codewords enumerated, lower-bound 9, upper-bound 15
Termination expected with information weight 6 at matrix 1
-----------------------------------------------------------------------------
Enumerating codewords with information weight 4 (w=4) using 2 matrices
Completed w= 4, 170016 codewords enumerated, lower-bound 12, upper-bound 15
Termination expected with information weight 6 at matrix 1
-----------------------------------------------------------------------------
Enumerating codewords with information weight 5 (w=5) using 2 matrices
Completed w= 5, 1360128 codewords enumerated, lower-bound 12, upper-bound 15
Termination expected with information weight 6 at matrix 1
-----------------------------------------------------------------------------
Enumerating codewords with information weight 6 (w=6) using 1 matrices
Completed w= 6, 4307072 codewords enumerated, lower-bound 15, upper-bound 15
-----------------------------------------------------------------------------
Minimum weight: 15
15
gap> 

gap> # Binary cyclic code [151,45,36]
gap> n := 151;;
gap> x := Indeterminate(GF(2));;
gap> F := Factors(x^n-1);;
gap> C := CheckPolCode(F[2]*F[3]*F[3]*F[4], n, GF(2));
a cyclic [151,45,1..50]31..75 code defined by check polynomial over GF(2)
gap> MinimumWeight(C);
[151,45] cyclic code over GF(2) - minimum weight evaluation
Known lower-bound: 1
The weight of the minimum weight codeword satisfies 0 mod 4 congruence
Enumerating codewords with information weight 1 (w=1)
    Found new minimum weight 56
    Found new minimum weight 44
Number of matrices required for codeword enumeration 1
Completed w= 1, 45 codewords enumerated, lower-bound 8, upper-bound 44
Termination expected with information weight 11
-----------------------------------------------------------------------------
Enumerating codewords with information weight 2 (w=2) using 1 matrix
Completed w= 2, 990 codewords enumerated, lower-bound 12, upper-bound 44
Termination expected with information weight 11
-----------------------------------------------------------------------------
Enumerating codewords with information weight 3 (w=3) using 1 matrix
   Found new minimum weight 40
   Found new minimum weight 36
Completed w= 3, 14190 codewords enumerated, lower-bound 16, upper-bound 36
Termination expected with information weight 9
-----------------------------------------------------------------------------
Enumerating codewords with information weight 4 (w=4) using 1 matrix
Completed w= 4, 148995 codewords enumerated, lower-bound 20, upper-bound 36
Termination expected with information weight 9
-----------------------------------------------------------------------------
Enumerating codewords with information weight 5 (w=5) using 1 matrix
Completed w= 5, 1221759 codewords enumerated, lower-bound 24, upper-bound 36
Termination expected with information weight 9
-----------------------------------------------------------------------------
Enumerating codewords with information weight 6 (w=6) using 1 matrix
Completed w= 6, 8145060 codewords enumerated, lower-bound 24, upper-bound 36
Termination expected with information weight 9
-----------------------------------------------------------------------------
Enumerating codewords with information weight 7 (w=7) using 1 matrix
Completed w= 7, 45379620 codewords enumerated, lower-bound 28, upper-bound 36
Termination expected with information weight 9
-----------------------------------------------------------------------------
Enumerating codewords with information weight 8 (w=8) using 1 matrix
Completed w= 8, 215553195 codewords enumerated, lower-bound 32, upper-bound 36
Termination expected with information weight 9
-----------------------------------------------------------------------------
Enumerating codewords with information weight 9 (w=9) using 1 matrix
Completed w= 9, 886163135 codewords enumerated, lower-bound 36, upper-bound 36
-----------------------------------------------------------------------------
Minimum weight: 36
36
</Example>

<!--
# Extended ternary quadratic residue code of length 48
n := 47;;
x := Indeterminate(GF(3));;
F := Factors(x^n-1);;
v := List([1..n], i->Zero(GF(3)));;
v := v + MutableCopyMat(VectorCodeword( Codeword(F[2]) ));;
G := CirculantMatrix(24, v);;
for i in [1..Size(G)] do; s:=Zero(GF(3));
for j in [1..Size(G[i])] do; s:=s+G[i][j]; od; Append(G[i], [ s ]);
od;;
C := GeneratorMatCodeNC(G, GF(3));
MinimumWeight(C);

# Binary cyclic code [151,45,36]
n := 151;;
x := Indeterminate(GF(2));;
F := Factors(x^n-1);;
C := CheckPolCode(F[2]*F[3]*F[3]*F[4], n, GF(2));
MinimumWeight(C);
-->


<ManSection>
<Func Name="DecreaseMinimumDistanceUpperBound" Arg=" C t m"/>

<Description>
<C>DecreaseMinimumDistanceUpperBound</C> is an implementation of the algorithm
for the minimum distance of a linear binary code <A>C</A> by Leon 
<Cite Key="Leon88"/>. 
This algorithm tries to find codewords with small minimum weights. 
The parameter <A>t</A> is at least <M>1</M> and less than 
the dimension of <A>C</A>.
The best results are obtained if it is close to the
dimension of the code. The parameter <A>m</A> gives the number of
runs that the algorithm will perform.
<P/>
The result returned is a record with two fields;  the first, <C>mindist</C>,
gives the lowest weight found, and <C>word</C> gives the corresponding
codeword.
(This was implemented before <C>MinimumDistanceLeon</C> but independently.
The older manual had given the command incorrectly, so the command
was only found after reading all the <E>*.gi</E> files in the
<Package>GUAVA</Package> library. Though both  <C>MinimumDistance</C> and
<C>MinimumDistanceLeon</C> often run much faster than 
<C>DecreaseMinimumDistanceUpperBound</C>, <C>DecreaseMinimumDistanceUpperBound</C>
appears to be more accurate than <C>MinimumDistanceLeon</C>.)
</Description>
</ManSection>

<Example>
gap> C:=RandomLinearCode(5,2,GF(2));
a  [5,2,?] randomly generated code over GF(2)
gap> DecreaseMinimumDistanceUpperBound(C,1,4);
rec( mindist := 3, word := [ 0*Z(2), Z(2)^0, Z(2)^0, 0*Z(2), Z(2)^0 ] )
gap> MinimumDistance(C);
3
gap> C:=RandomLinearCode(8,4,GF(2));
a  [8,4,?] randomly generated code over GF(2)
gap> DecreaseMinimumDistanceUpperBound(C,3,4);
rec( mindist := 2,
  word := [ Z(2)^0, 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), Z(2)^0 ] )
gap> MinimumDistance(C);
2
</Example>

<ManSection>
<Func Name="MinimumDistanceRandom" Arg=" C num s "/>

<Description>
<C>MinimumDistanceRandom</C> returns an upper bound for the minimum distance 
<M>d_{random}</M> of a linear binary code <A>C</A>, using a
probabilistic polynomial time algorithm. Briefly:
Let <A>C</A> be a linear code of dimension <M>k</M> over 
<M>GF(q)</M> as above. The algorithm has input parameters <M>num</M> and <M>s</M>,
where <M>s</M> is an integer between <M>2</M> and <M>n-1</M>, and 
<M>num</M> is an integer greater than or equal to <M>1</M>.

<List>
<Item>  
Find a generator matrix <M>G</M> of <M>C</M>.
</Item>

<Item>
Randomly permute the columns of <M>G</M>, written <M>G_p</M>..
</Item>

<Item>
<Display>
G=(A, B)
</Display>
with <M>A</M> a <M>k\times s</M> matrix. If <M>A</M> is the
zero matrix then return `method fails'. 
</Item>

<Item>
Search <M>A</M> for at most <M>5</M> rows that lead to codewords, 
in the code <M>C_A</M> with generator matrix <M>A</M>, of
minimum weight.
</Item>

<Item>
For these codewords, use the associated linear combination to
compute the weight of the whole word in <A>C</A>.
Return this weight and codeword.
</Item>
</List>
This probabilistic algorithm 
is repeated <A>num</A> times (with different random permutations of the 
rows of <M>G</M> each time) and the weight and codeword of the lowest
occurring weight is taken.
</Description>
</ManSection>

<Example>
gap> C:=RandomLinearCode(60,20,GF(2));
a  [60,20,?] randomly generated code over GF(2)
gap> #mindist(C);time;
gap> #mindistleon(C,10,30);time; #doesn't work well
gap> a:=MinimumDistanceRandom(C,10,30);time; # done 10 times -with fastest time!!

 This is a probabilistic algorithm which may return the wrong answer.
[ 12, [ 0 0 0 0 0 0 1 0 1 0 0 0 0 0 0 0 1 1 0 0 1 0 0 0 1 0 0 0 0 0 0 1 0 0 
        1 0 0 0 0 0 0 0 0 0 1 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 ] ]
130
gap> a[2] in C;
true
gap> b:=DecreaseMinimumDistanceUpperBound(C,10,1); time; #only done once!
rec( mindist := 12, word := [ 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), 
      Z(2)^0, 0*Z(2), Z(2)^0, 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), 
      0*Z(2), Z(2)^0, Z(2)^0, 0*Z(2), 0*Z(2), Z(2)^0, 0*Z(2), 0*Z(2), 0*Z(2), 
      Z(2)^0, 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), Z(2)^0, 0*Z(2), 
      0*Z(2), Z(2)^0, 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), 
      0*Z(2), 0*Z(2), Z(2)^0, 0*Z(2), 0*Z(2), 0*Z(2), Z(2)^0, 0*Z(2), 0*Z(2), 
      0*Z(2), 0*Z(2), Z(2)^0, 0*Z(2), 0*Z(2), 0*Z(2), 0*Z(2), Z(2)^0, 0*Z(2) ] )
649
gap> Codeword(b!.word) in C;
true
gap> MinimumDistance(C);time;
12
196
gap> c:=MinimumDistanceLeon(C);time;
12
66
gap> C:=RandomLinearCode(30,10,GF(3));
a  [30,10,?] randomly generated code over GF(3)
gap> a:=MinimumDistanceRandom(C,10,10);time;

 This is a probabilistic algorithm which may return the wrong answer.
[ 13, [ 0 0 0 1 0 0 0 0 0 0 1 0 2 2 1 1 0 2 2 0 1 0 2 1 0 0 0 1 0 2 ] ]
229
gap> a[2] in C;
true
gap> MinimumDistance(C);time;
9
45
gap> c:=MinimumDistanceLeon(C);
Code must be binary. Quitting.
0
gap> a:=MinimumDistanceRandom(C,1,29);time;

 This is a probabilistic algorithm which may return the wrong answer.
[ 10, [ 0 0 1 0 2 0 2 0 1 0 0 0 0 0 0 1 0 1 0 0 1 0 0 0 0 0 2 2 2 0 ] ]
53
</Example>
<!--

-->


<Index>
<M>t(n,k)</M>
</Index>
<Index>
covering code
</Index>

<ManSection>
<Func Name="CoveringRadius" Arg=" C "/>

<Description>
<C>CoveringRadius</C> returns the <E>covering radius</E> of 
a linear code <A>C</A>. This is the smallest number <M>r</M> with the 
property that each element <M>v</M> of the ambient vector space of
<A>C</A> has at most a distance <M>r</M> to the code <A>C</A>. 
So for each vector <M>v</M>
there must be an element <M>c</M> of <A>C</A> with 
<M>d(v,c) \leq r</M>.
The smallest covering radius of any <M>[n,k]</M> binary
linear code is denoted <M>t(n,k)</M>. A binary linear code
with reasonable small covering radius is called a
<E>covering code</E>.
<P/>
If <A>C</A> is  a perfect code (see  
<Ref Func="IsPerfectCode" Style="Number"/>), the covering  radius is
equal to <M>t</M>,  the number of errors the code can correct, where 
<M>d = 2t+1</M>, with <M>d</M> the minimum distance of 
<A>C</A> (see 
<Ref Func="MinimumDistance" Style="Number"/>).
<P/>
If there exists a function called <C>SpecialCoveringRadius</C> in the
`operations' field of the code, then this function will be called to
compute the covering radius of the code.
At the moment, no code-specific functions are implemented.
<P/>
If the length of <C>BoundsCoveringRadius</C> 
(see <Ref Func="BoundsCoveringRadius" Style="Number"/>),
is 1, then the value in

<Verb>
C.boundsCoveringRadius
</Verb>

is returned.
Otherwise, the function

<Verb>
C.operations.CoveringRadius
</Verb>

is executed, unless the redundancy of <A>C</A> is too large.  
In the last case, a warning is issued.
<P/>
The algorithm used to compute the covering radius is the following.
First, <C>CosetLeadersMatFFE</C> is used to compute
the list of coset leaders (which returns a codeword in
each coset of <M>GF(q)^n/C</M> of minimum weight).
Then <C>WeightVecFFE</C> is used to compute the weight
of each of these coset leaders. The program returns the
maximum of these weights.

<!--
If you want to overrule this restriction, you might want to execute

<Verb>
C.operations.CoveringRadius
</Verb>

yourself. However, this algorithm might also issue a warning that it
cannot be executed, but this warning is sometimes issued too late,
resulting in GAP exiting with an memory error. If it does run, it  can
only be stopped by pressing <B>ctrl-C</B> twice, thereby quitting GAP.  It
will not enter the usual break-loop. Therefore it is recommended to  save
your work before trying <C>code.operations.CoveringRadius</C>.

************
This seems to be wrong, since GAP doesn't like this command:

gap> H := RandomLinearCode(10, 5, GF(2));
a  [10,5,?] randomly generated code over GF(2)
gap> CoveringRadius( H );
3
gap> H.operations.CoveringRadius;
Error, illegal access to record component `obj.operations'
of the object <obj>. (Objects by default do not have record components.
The error might be a relic from translated GAP3 code.)       called from
<function>( <arguments> ) called from read-eval-loop
Entering break read-eval-print loop ...
you can 'quit;' to quit to outer loop, or
you can 'return;' to continue
brk>
************
-->
</Description>
</ManSection>

<Example>
gap> H := RandomLinearCode(10, 5, GF(2));
a  [10,5,?] randomly generated code over GF(2)
gap> CoveringRadius(H);
3
gap> H := HammingCode(4, GF(2));; IsPerfectCode(H);
true
gap> CoveringRadius(H);
1                       # Hamming codes have minimum distance 3
gap> CoveringRadius(ReedSolomonCode(7,4));
3 
gap> CoveringRadius( BCHCode( 17, 3, GF(2) ) );
3
gap> CoveringRadius( HammingCode( 5, GF(2) ) );
1
gap> C := ReedMullerCode( 1, 9 );;
gap> CoveringRadius( C );
CoveringRadius: warning, the covering radius of
this code cannot be computed straightforward.
Try to use IncreaseCoveringRadiusLowerBound( code ).
(see the manual for more details).
The covering radius of code lies in the interval:
[ 240 .. 248 ]
</Example>
<!--
H := RandomLinearCode(10, 5, GF(2));
CoveringRadius(H);
H := HammingCode(4, GF(2));; IsPerfectCode(H);
CoveringRadius(H);
CoveringRadius(ReedSolomonCode(7,4));
CoveringRadius( BCHCode( 17, 3, GF(2) ) );
CoveringRadius( HammingCode( 5, GF(2) ) );
C := ReedMullerCode( 1, 9 );;
CoveringRadius( C );
-->


See also the <Package>GUAVA</Package>  
commands relating to bounds on the
minimum distance in section
<Ref Label="Covering radius bounds on codes" Style="Number"/>.

<ManSection>
<Func Name="SetCoveringRadius" Arg=" C intlist "/>

<Description>
<C>SetCoveringRadius</C> enables the user to set the covering radius
herself, instead of letting  <Package>GUAVA</Package> 
compute it.
If <A>intlist</A> is an integer, <Package>GUAVA</Package>  
will simply put it in the `boundsCoveringRadius' field.
If it is a list of integers, however, it will intersect this list
with the `boundsCoveringRadius' field, thus taking the best of both
lists.
If this would leave an empty list, the field is set to <A>intlist</A>.
Because some other computations use the covering radius of the code,
it is important that the entered value is not wrong, otherwise
new results may be invalid.
</Description>
</ManSection>

<Example>
gap> C := BCHCode( 17, 3, GF(2) );;
gap> BoundsCoveringRadius( C );
[ 3 .. 4 ]
gap> SetCoveringRadius( C, [ 2 .. 3 ] );
gap> BoundsCoveringRadius( C );
[ [ 2 .. 3 ] ]
</Example>
<!--
C := BCHCode( 17, 3, GF(2) );;
BoundsCoveringRadius( C );
SetCoveringRadius( C, [ 2 .. 3 ] );
BoundsCoveringRadius( C );
-->


</Section>

<Section>
<Heading>
Distributions
</Heading>
<Label Name="Distributions"/>


<ManSection>
<Func Name="MinimumWeightWords" Arg=" C "/>

<Description>
<C>MinimumWeightWords</C> returns the list of minimum weight codewords of 
<A>C</A>. 
<P/>
This algorithm is written in GAP is slow, so is only suitable for small codes.
<P/>
This does not call the very fast function <C>MinimumWeight</C>
(see <Ref Func="MinimumWeight" Style="Number"/>).
</Description>
</ManSection>

<Example>
gap> C:=HammingCode(3,GF(2));
a linear [7,4,3]1 Hamming (3,2) code over GF(2)
gap> MinimumWeightWords(C);
[ [ 1 0 0 0 0 1 1 ], [ 0 1 0 1 0 1 0 ], [ 0 1 0 0 1 0 1 ], [ 1 0 0 1 1 0 0 ], [ 0 0 1 0 1 1 0 ],
  [ 0 0 1 1 0 0 1 ], [ 1 1 1 0 0 0 0 ] ]

</Example>
<!--
C:=HammingCode(3,GF(2));
MinimumWeightWords(C);
-->


<ManSection>
<Func Name="WeightDistribution" Arg=" C "/>

<Description>
<C>WeightDistribution</C> returns the weight distribution of 
<A>C</A>, as a vector. The <M>i^{th}</M> element of this
vector contains the number of elements of <A>C</A> with 
weight <M>i-1</M>.  For linear codes, the weight
distribution is equal to the inner distribution (see
<Ref Func="InnerDistribution" Style="Number"/>).
If <M>w</M> is the weight distribution of 
a linear code <A>C</A>, it must
have the zero codeword, so <M>w[1] = 1</M> (one word of weight 0).
<P/>
Some codes, such as the Hamming codes, have precomputed
weight distributions. For others, the program
WeightDistribution calls the GAP program
<C>DistancesDistributionMatFFEVecFFE</C>,
which is written in C. See also
<C>CodeWeightEnumerator</C>.
</Description>
</ManSection>

<Example>
gap> WeightDistribution( ConferenceCode(9) );
[ 1, 0, 0, 0, 0, 18, 0, 0, 0, 1 ]
gap> WeightDistribution( RepetitionCode( 7, GF(4) ) );
[ 1, 0, 0, 0, 0, 0, 0, 3 ]
gap> WeightDistribution( WholeSpaceCode( 5, GF(2) ) );
[ 1, 5, 10, 10, 5, 1 ] 
</Example>
<!--
WeightDistribution( ConferenceCode(9) );
WeightDistribution( RepetitionCode( 7, GF(4) ) );
WeightDistribution( WholeSpaceCode( 5, GF(2) ) );
-->

<ManSection>
<Func Name="InnerDistribution" Arg=" C "/>

<Description>
<C>InnerDistribution</C> returns the inner distribution 
of <A>C</A>. The <M>i^{th}</M> element of the vector contains the
average number of  elements of <A>C</A> at
distance <M>i-1</M> to an element of <A>C</A>.  
For  linear  codes, the inner distribution is equal 
to the weight distribution (see
<Ref Func="WeightDistribution" Style="Number"/>).
<P/>
Suppose <M>w</M> is the inner distribution of <A>C</A>. Then  
<M>w[1] = 1</M>, because each element of <A>C</A> has 
exactly one element at distance zero (the element
itself). The minimum distance of  <A>C</A> is the smallest  
value <M>d > 0</M> with
<M>w[d+1] \neq 0</M>, because a distance between zero  
and <M>d</M> never occurs. See 
<Ref Func="MinimumDistance" Style="Number"/>.
</Description>
</ManSection>

<Example>
gap> InnerDistribution( ConferenceCode(9) );
[ 1, 0, 0, 0, 63/5, 9/5, 18/5, 0, 9/10, 1/10 ]
gap> InnerDistribution( RepetitionCode( 7, GF(4) ) );
[ 1, 0, 0, 0, 0, 0, 0, 3 ] 
</Example>
<!--
InnerDistribution( ConferenceCode(9) );
InnerDistribution( RepetitionCode( 7, GF(4) ) );
-->

<Index>
distance
</Index>

<ManSection>
<Func Name="DistancesDistribution" Arg=" C w "/>

<Description>
<C>DistancesDistribution</C> returns the distribution 
of the distances of all
elements of <A>C</A> to a codeword <A>w</A> in the same  vector space. 
The <M>i^{th}</M>
element of the distance distribution is the  
number of codewords of <A>C</A>
that have distance <M>i-1</M> to <A>w</A>. 
The smallest value <M>d</M> with <M>w[d+1] \neq 0</M>, is 
defined as the <E>distance to</E> <A>C</A> 
(see 
<Ref Func="MinimumDistance" Style="Number"/>).
</Description>
</ManSection>

<Example>
gap> H := HadamardCode(20);
a (20,40,10)6..8 Hadamard code of order 20 over GF(2)
gap> c := Codeword("10110101101010010101", H);
[ 1 0 1 1 0 1 0 1 1 0 1 0 1 0 0 1 0 1 0 1 ]
gap> DistancesDistribution(H, c);
[ 0, 0, 0, 0, 0, 1, 0, 7, 0, 12, 0, 12, 0, 7, 0, 1, 0, 0, 0, 0, 0 ]
gap> MinimumDistance(H, c);
5                           # distance to H 
</Example>
<!--
H := HadamardCode(20);
c := Codeword("10110101101010010101", H);
DistancesDistribution(H, c);
MinimumDistance(H, c);
-->

<ManSection>
<Func Name="OuterDistribution" Arg=" C "/>

<Description>
The function <C>OuterDistribution</C> returns a 
list of length <M>q^n</M>, where
<M>q</M> is the size of the base field of <A>C</A> and <M>n</M>
is the word length. The elements of the list consist of pairs,
the first coordinate being an element of 
<M>GF(q)^n</M> (this is a codeword type) and the 
second coordinate being a distribution 
of distances to the code (a list of integers). 
This table is <E>very</E> large, and for 
<M>n > 20</M> it will not fit
in the memory of most computers. 
The function <C>DistancesDistribution</C>
(see 
<Ref Func="DistancesDistribution" Style="Number"/>) 
can be used  to calculate one entry of the list.
</Description>
</ManSection>

<Example>
gap> C := RepetitionCode( 3, GF(2) );
a cyclic [3,1,3]1 repetition code over GF(2)
gap> OD := OuterDistribution(C);
[ [ [ 0 0 0 ], [ 1, 0, 0, 1 ] ], [ [ 1 1 1 ], [ 1, 0, 0, 1 ] ],
  [ [ 0 0 1 ], [ 0, 1, 1, 0 ] ], [ [ 1 1 0 ], [ 0, 1, 1, 0 ] ],
  [ [ 1 0 0 ], [ 0, 1, 1, 0 ] ], [ [ 0 1 1 ], [ 0, 1, 1, 0 ] ],
  [ [ 0 1 0 ], [ 0, 1, 1, 0 ] ], [ [ 1 0 1 ], [ 0, 1, 1, 0 ] ] ]
gap> WeightDistribution(C) = OD[1][2];
true
gap> DistancesDistribution( C, Codeword("110") ) = OD[4][2];
true 
</Example>
<!--
C := RepetitionCode( 3, GF(2) );
OD := OuterDistribution(C);
WeightDistribution(C) = OD[1][2];
DistancesDistribution( C, Codeword("110") ) = OD[4][2];
-->

</Section>

<Section>
<Heading>
Decoding Functions
</Heading>
<Label Name="Decoding Functions"/>

<ManSection>
<Func Name="Decode" Arg=" C r "/>

<Description>
<C>Decode</C> decodes <A>r</A> (a 'received word') 
with respect to code <A>C</A> and returns the 
`message word' (i.e., the information digits associated to
the codeword <M>c \in C</M> closest to <A>r</A>). Here
<A>r</A> can be a <Package>GUAVA</Package>
codeword or a list of codewords. 
First, possible errors in <A>r</A> are corrected, then the
codeword is decoded to an <E>information codeword</E> <M>m</M>
(and not an element of <A>C</A>).  
If the code record has a field `specialDecoder', 
this special algorithm is used to decode
the vector.  Hamming codes, 
<!--
BCH codes, - removed due to an unfixed bug
-->
cyclic codes,
and generalized Reed-Solomon have such a special algorithm.
(The algorithm used for BCH codes is the
Sugiyama algorithm described, for example, in 
section 5.4.3 of <Cite Key="HP03"/>. A special decoder has 
also being written for the generalized Reed-Solomon code
using the interpolation algorithm. For cyclic codes, the
error-trapping algorithm is used.)
If <A>C</A> is linear and no special decoder 
field has been set then syndrome decoding is used. 
Otherwise (when <A>C</A> is non-linear), the nearest neighbor decoding 
algorithm is used (which is very slow).
<P/>
A special decoder can be created by defining a function

<Verb>
C!.SpecialDecoder := function(C, r) ... end;
</Verb>

The function uses the arguments <A>C</A> (the code 
record itself) and <A>r</A> (a
vector of the codeword type) to decode <A>r</A> to an information 
vector. A normal decoder would take a codeword <A>r</A> of the
same word length and field as <A>C</A>, and would return 
an information vector of length <M>k</M>, the
dimension of <A>C</A>. The user is not restricted to these normal demands
though, and can for instance define a decoder for non-linear codes.
<P/>
Encoding is done by multiplying the
information vector with the code (see 
<Ref Label="Operations for Codes" Style="Number"/>).

</Description>
</ManSection>

<Example>
gap> C := HammingCode(3);
a linear [7,4,3]1 Hamming (3,2) code over GF(2)
gap> c := "1010"*C;                    # encoding
[ 1 0 1 1 0 1 0 ]
gap> Decode(C, c);                     # decoding
[ 1 0 1 0 ]
gap> Decode(C, Codeword("0010101"));
[ 1 1 0 1 ]                            # one error corrected
gap> C!.SpecialDecoder := function(C, c)
> return NullWord(Dimension(C));
> end;
function ( C, c ) ... end
gap> Decode(C, c);
[ 0 0 0 0 ]           # new decoder always returns null word 
</Example>
<!--
C := HammingCode(3);
c := "1010"*C;                    # encoding
Decode(C, c);                     # decoding
Decode(C, Codeword("0010101"));
C!.SpecialDecoder := function(C, c)
 return NullWord(Dimension(C));
end;
Decode(C, c);
-->

<ManSection>
<Func Name="Decodeword" Arg=" C r "/>

<Description>
<C>Decodeword</C> decodes <A>r</A> (a 'received word') 
with respect to code <A>C</A> and returns the 
codeword <M>c \in C</M> closest to <A>r</A>. Here
<A>r</A> can be a <Package>GUAVA</Package>
codeword or a list of codewords. 
If the code record has a field `specialDecoder', 
this special algorithm is used to decode
the vector.  Hamming codes, generalized Reed-Solomon codes, 
and BCH codes have such a special algorithm.
(The algorithm used for BCH codes is the
Sugiyama algorithm described, for example, in 
section 5.4.3 of <Cite Key="HP03"/>. The algorithm used for
generalized Reed-Solomon codes is the ``interpolation 
algorithm'' described for example in chapter 5 of 
<Cite Key="JH04"/>.)
If <A>C</A> is linear and no special decoder 
field has been set then syndrome decoding is used. 
Otherwise, when <A>C</A> is non-linear, the nearest neighbor algorithm has
been implemented (which should only be used for small-sized
codes).
</Description>
</ManSection>

<Example>
gap> C := HammingCode(3);
a linear [7,4,3]1 Hamming (3,2) code over GF(2)
gap> c := "1010"*C;                    # encoding
[ 1 0 1 1 0 1 0 ]
gap> Decodeword(C, c);                     # decoding
[ 1 0 1 1 0 1 0 ]
gap>
gap> R:=PolynomialRing(GF(11),["t"]);
GF(11)[t]
gap> P:=List([1,3,4,5,7],i->Z(11)^i);
[ Z(11), Z(11)^3, Z(11)^4, Z(11)^5, Z(11)^7 ]
gap> C:=GeneralizedReedSolomonCode(P,3,R);
a linear [5,3,1..3]2  generalized Reed-Solomon code over GF(11)
gap> MinimumDistance(C);
3
gap> c:=Random(C);
[ 0 9 6 2 1 ]
gap> v:=Codeword("09620");
[ 0 9 6 2 0 ]
gap> GeneralizedReedSolomonDecoderGao(C,v);
[ 0 9 6 2 1 ]
gap> Decodeword(C,v); # calls the special interpolation decoder
[ 0 9 6 2 1 ]
gap> G:=GeneratorMat(C);
[ [ Z(11)^0, 0*Z(11), 0*Z(11), Z(11)^8, Z(11)^9 ],
  [ 0*Z(11), Z(11)^0, 0*Z(11), Z(11)^0, Z(11)^8 ],
  [ 0*Z(11), 0*Z(11), Z(11)^0, Z(11)^3, Z(11)^8 ] ]
gap> C1:=GeneratorMatCode(G,GF(11));
a linear [5,3,1..3]2 code defined by generator matrix over GF(11)
gap> Decodeword(C,v); # calls syndrome decoding
[ 0 9 6 2 1 ]
</Example>
<!--
C := HammingCode(3);
c := "1010"*C;                    # encoding
Decodeword(C, c);                     # decoding
R:=PolynomialRing(GF(11),["t"]);
P:=List([1,3,4,5,7],i->Z(11)^i);
C:=GeneralizedReedSolomonCode(P,3,R);
#########a linear [5,3,1..3]2  generalized Reed-Solomon code over GF(11)
MinimumDistance(C);
c:=Random(C);      ####### [ 0 9 6 2 1 ]
v:=Codeword("09620");
GeneralizedReedSolomonDecoderGao(C,v);
                   ########   [ 0 9 6 2 1 ]
Decodeword(C,v);
                   ########   [ 0 9 6 2 1 ]
Decodeword(C,v); time;
                   ########   [ 0 9 6 2 1 ]
                   ###         5
G:=GeneratorMat(C);
C1:=GeneratorMatCode(G,GF(11));
#########a linear [5,3,1..3]2 code defined by generator matrix over GF(11)
Decodeword(C,v); time;
                   #########  [ 0 9 6 2 1 ]
                   #########   9


-->


<ManSection>
<Func Name="GeneralizedReedSolomonDecoderGao" Arg=" C r "/>

<Description>
<C>GeneralizedReedSolomonDecoderGao</C> decodes <A>r</A> (a 'received word') 
to a codeword  <M>c \in C</M>
in a generalized Reed-Solomon code <A>C</A>
(see <Ref Func="GeneralizedReedSolomonCode" Style="Number"/>), 
closest to <A>r</A>. Here
<A>r</A> must be a <Package>GUAVA</Package>
codeword. 
If the code record does not have name 
`generalized Reed-Solomon code' then an error is returned.
Otherwise, the Gao decoder <Cite Key="Gao03"/> is used 
to compute <M>c</M>.
<P/>
For long codes, this method is faster in practice than the
interpolation method used in <C>Decodeword</C>.
</Description>
</ManSection>

<Example>
gap> R:=PolynomialRing(GF(11),["t"]);
GF(11)[t]
gap> P:=List([1,3,4,5,7],i->Z(11)^i);
[ Z(11), Z(11)^3, Z(11)^4, Z(11)^5, Z(11)^7 ]
gap> C:=GeneralizedReedSolomonCode(P,3,R);
a linear [5,3,1..3]2  generalized Reed-Solomon code over GF(11)
gap> MinimumDistance(C);
3
gap> c:=Random(C);
[ 0 9 6 2 1 ]
gap> v:=Codeword("09620");
[ 0 9 6 2 0 ]
gap> GeneralizedReedSolomonDecoderGao(C,v); 
[ 0 9 6 2 1 ]
</Example>
<!--
R:=PolynomialRing(GF(11),["t"]);
P:=List([1,3,4,5,7],i->Z(11)^i);
C:=GeneralizedReedSolomonCode(P,3,R);
MinimumDistance(C);
c:=Random(C);

GeneralizedReedSolomonDecoderGao(C,v); time;
Decodeword(C,v); time;

R:=PolynomialRing(GF(71),["x"]);
P:=List([1..70],i->Z(71)^i);
C:=GeneralizedReedSolomonCode(P,3,R);
MinimumDistance(C);
c:=Random(C);
v:=ShallowCopy(c);; 
v:=ShallowCopy(c);; for i in [1..30] do v[i]:=Zero(GF(71)); od;
v:=Codeword(v,C);
GeneralizedReedSolomonDecoderGao(C,v); time;
Decodeword(C,v); time;

R:=PolynomialRing(GF(2^8),["y"]);
P:=List([1..(2^8-1)],i->Z(2^8)^i);;
C:=GeneralizedReedSolomonCode(P,3,R);
#MinimumDistance(C); ## too time-consuming...it is MDS though
c:=Random(C);
v:=ShallowCopy(c);; 
v:=ShallowCopy(c);; for i in [1..100] do v[i]:=Zero(GF(2^8)); od;
v:=Codeword(v,C);
GeneralizedReedSolomonDecoderGao(C,v); time;
Decodeword(C,v); time; #uses interpolation decoding...

-->


<ManSection>
<Func Name="GeneralizedReedSolomonListDecoder" Arg=" C r tau"/>

<Description>
<C>GeneralizedReedSolomonListDecoder</C> implements
Sudans list-decoding algorithm 
(see section 12.1 of <Cite Key="JH04"/>) for ``low rate''
Reed-Solomon codes.
It returns the list of all codewords in C which are a distance
of at most <A>tau</A> from <A>r</A> (a 'received word').
<A>C</A> must be a generalized Reed-Solomon code <A>C</A>
(see <Ref Func="GeneralizedReedSolomonCode" Style="Number"/>) and
<A>r</A> must be a <Package>GUAVA</Package>
codeword. 

</Description>
</ManSection>

<Example>
gap> F:=GF(16);
GF(2^4)
gap>
gap> a:=PrimitiveRoot(F);; b:=a^7;; b^4+b^3+1; 
0*Z(2)
gap> Pts:=List([0..14],i->b^i);
[ Z(2)^0, Z(2^4)^7, Z(2^4)^14, Z(2^4)^6, Z(2^4)^13, Z(2^2), Z(2^4)^12, Z(2^4)^4,
  Z(2^4)^11, Z(2^4)^3, Z(2^2)^2, Z(2^4)^2, Z(2^4)^9, Z(2^4), Z(2^4)^8 ]
gap> x:=X(F);;
gap> R1:=PolynomialRing(F,[x]);;
gap> vars:=IndeterminatesOfPolynomialRing(R1);;
gap> y:=X(F,vars);;
gap> R2:=PolynomialRing(F,[x,y]);;
gap> C:=GeneralizedReedSolomonCode(Pts,3,R1); 
a linear [15,3,1..13]10..12  generalized Reed-Solomon code over GF(16)
gap> MinimumDistance(C); ## 6 error correcting
13
gap> z:=Zero(F);;
gap> r:=[z,z,z,z,z,z,z,z,b^6,b^2,b^5,b^14,b,b^7,b^11];; 
gap> r:=Codeword(r);
[ 0 0 0 0 0 0 0 0 a^12 a^14 a^5 a^8 a^7 a^4 a^2 ]
gap> cs:=GeneralizedReedSolomonListDecoder(C,r,2); time;
[ [ 0 a^9 a^3 a^13 a^6 a^10 a^11 a a^12 a^14 a^5 a^8 a^7 a^4 a^2 ],
  [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ] ]
250
gap> c1:=cs[1]; c1 in C;
[ 0 a^9 a^3 a^13 a^6 a^10 a^11 a a^12 a^14 a^5 a^8 a^7 a^4 a^2 ]
true
gap> c2:=cs[2]; c2 in C;
[ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ]
true
gap> WeightCodeword(c1-r);
7
gap> WeightCodeword(c2-r);
7
</Example>
<!--
F:=GF(16);
a:=PrimitiveRoot(F);; b:=a^7; b^4+b^3+1; ## alpha in JH Ex 12.1.1
Pts:=List([0..14],i->b^i);
x:=X(F);;
R1:=PolynomialRing(F,[x]);;
vars:=IndeterminatesOfPolynomialRing(R1);;
y:=X(F,vars);;
R2:=PolynomialRing(F,[x,y]);;
C:=GeneralizedReedSolomonCode(Pts,3,R1); MinimumDistance(C);
z:=Zero(F);
r:=[z,z,z,z,z,z,z,z,b^6,b^2,b^5,b^14,b,b^7,b^11];; 
r:=Codeword(r);
cs:=GeneralizedReedSolomonListDecoder(C,r,2); time;
c1:=cs[1]; c1 in C;
c2:=cs[2]; c2 in C;
WeightCodeword(c1-r);
WeightCodeword(c2-r);
-->

<ManSection>
<Func Name="BitFlipDecoder" Arg=" C r "/>

<Description>
The iterative decoding method
<C>BitFlipDecoder</C> must only be applied to LDPC codes.
For more information on LDPC codes, refer to Section
<Ref Label="LDPC" Style="Number"/>.
For these codes, <C>BitFlipDecoder</C> decodes very quickly.
(Warning: it can give wildly wrong results for arbitrary
binary linear codes.)
The bit flipping algorithm is described for example in Chapter 13 of 
<Cite Key="JH04"/>.
</Description>
</ManSection>

<Example>
gap> C:=HammingCode(4,GF(2));
a linear [15,11,3]1 Hamming (4,2) code over GF(2)
gap> c:=Random(C);
[ 0 0 0 1 0 0 1 0 0 1 1 0 1 0 1 ]
gap> v:=List(c);
[ 0*Z(2), 0*Z(2), 0*Z(2), Z(2)^0, 0*Z(2), 0*Z(2), Z(2)^0, 0*Z(2), 0*Z(2),
  Z(2)^0, Z(2)^0, 0*Z(2), Z(2)^0, 0*Z(2), Z(2)^0 ]
gap> v[1]:=Z(2)+v[1]; # flip 1st bit of c to create an error
Z(2)^0
gap> v:=Codeword(v);
[ 1 0 0 1 0 0 1 0 0 1 1 0 1 0 1 ]
gap> BitFlipDecoder(C,v);
[ 0 0 0 1 0 0 1 0 0 1 1 0 1 0 1 ]


</Example>
<!--
C:=HammingCode(4,GF(2));
c:=Random(C);
v:=List(c);
v[1]:=Z(2)+v[1]; # flip 1st bit of c to create an error
v:=Codeword(v);
BitFlipDecoder(C,v);
-->


<ManSection>
<Func Name="NearestNeighborGRSDecodewords" Arg=" C v dist"/>

<Description>
<C>NearestNeighborGRSDecodewords</C> finds all 
generalized Reed-Solomon codewords within distance 
<A>dist</A> from <A>v</A> <E>and</E> the associated polynomial,
using ``brute force''.
Input: <A>v</A> is a received vector (a <Package>GUAVA</Package> codeword),
<A>C</A> is a GRS code,
<A>dist</A> > 0 is the distance from <A>v</A> to search in <A>C</A>.
Output: a list of pairs <M>[c,f(x)]</M>, where <M>wt(c-v)\leq dist-1</M>
and <M>c = (f(x_1),...,f(x_n))</M>.
</Description>
</ManSection>

<Example>
gap> F:=GF(16);
GF(2^4)
gap> a:=PrimitiveRoot(F);; b:=a^7; b^4+b^3+1;
Z(2^4)^7
0*Z(2)
gap> Pts:=List([0..14],i->b^i);
[ Z(2)^0, Z(2^4)^7, Z(2^4)^14, Z(2^4)^6, Z(2^4)^13, Z(2^2), Z(2^4)^12,
  Z(2^4)^4, Z(2^4)^11, Z(2^4)^3, Z(2^2)^2, Z(2^4)^2, Z(2^4)^9, Z(2^4),
  Z(2^4)^8 ]
gap> x:=X(F);;
gap> R1:=PolynomialRing(F,[x]);;
gap> vars:=IndeterminatesOfPolynomialRing(R1);;
gap> y:=X(F,vars);;
gap> R2:=PolynomialRing(F,[x,y]);;
gap> C:=GeneralizedReedSolomonCode(Pts,3,R1);
a linear [15,3,1..13]10..12  generalized Reed-Solomon code over GF(16)
gap> MinimumDistance(C); # 6 error correcting
13
gap> z:=Zero(F);
0*Z(2)
gap> r:=[z,z,z,z,z,z,z,z,b^6,b^2,b^5,b^14,b,b^7,b^11];; # 7 errors
gap> r:=Codeword(r);
[ 0 0 0 0 0 0 0 0 a^12 a^14 a^5 a^8 a^7 a^4 a^2 ]
gap> cs:=NearestNeighborGRSDecodewords(C,r,7);
[ [ [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ], 0*Z(2) ],
  [ [ 0 a^9 a^3 a^13 a^6 a^10 a^11 a a^12 a^14 a^5 a^8 a^7 a^4 a^2 ], x_1+Z(2)^0 ] ]
</Example>
<!--
F:=GF(16);
a:=PrimitiveRoot(F);; b:=a^7; b^4+b^3+1; 
Pts:=List([0..14],i->b^i);
x:=X(F);;
R1:=PolynomialRing(F,[x]);;
vars:=IndeterminatesOfPolynomialRing(R1);;
y:=X(F,vars);;
R2:=PolynomialRing(F,[x,y]);;
C:=GeneralizedReedSolomonCode(Pts,3,R1); 
MinimumDistance(C); # 6 error correcting
z:=Zero(F);
r:=[z,z,z,z,z,z,z,z,b^6,b^2,b^5,b^14,b,b^7,b^11];; # 7 errors
r:=Codeword(r);
cs:=NearestNeighborGRSDecodewords(C,r,7);
-->

<ManSection>
<Func Name="NearestNeighborDecodewords" Arg=" C v dist"/>

<Description>
<C>NearestNeighborDecodewords</C> finds all 
codewords in a linear code <A>C</A> within distance 
<A>dist</A> from <A>v</A>, using ``brute force''.
Input: <A>v</A> is a received vector (a <Package>GUAVA</Package> codeword),
<A>C</A> is a linear code,
<A>dist</A> > 0 is the distance from <A>v</A> to search in <A>C</A>.
Output: a list of <M>c \in C</M>, where <M>wt(c-v)\leq dist-1</M>.
</Description>
</ManSection>

<Example>
gap> F:=GF(16);
GF(2^4)
gap> a:=PrimitiveRoot(F);; b:=a^7; b^4+b^3+1;
Z(2^4)^7
0*Z(2)
gap> Pts:=List([0..14],i->b^i);
[ Z(2)^0, Z(2^4)^7, Z(2^4)^14, Z(2^4)^6, Z(2^4)^13, Z(2^2), Z(2^4)^12,
  Z(2^4)^4, Z(2^4)^11, Z(2^4)^3, Z(2^2)^2, Z(2^4)^2, Z(2^4)^9, Z(2^4),
  Z(2^4)^8 ]
gap> x:=X(F);;
gap> R1:=PolynomialRing(F,[x]);;
gap> vars:=IndeterminatesOfPolynomialRing(R1);;
gap> y:=X(F,vars);;
gap> R2:=PolynomialRing(F,[x,y]);;
gap> C:=GeneralizedReedSolomonCode(Pts,3,R1);
a linear [15,3,1..13]10..12  generalized Reed-Solomon code over GF(16)
gap> MinimumDistance(C);
13
gap> z:=Zero(F);
0*Z(2)
gap> r:=[z,z,z,z,z,z,z,z,b^6,b^2,b^5,b^14,b,b^7,b^11];;
gap> r:=Codeword(r);
[ 0 0 0 0 0 0 0 0 a^12 a^14 a^5 a^8 a^7 a^4 a^2 ]
gap> cs:=NearestNeighborDecodewords(C,r,7);
[ [ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ], 
  [ 0 a^9 a^3 a^13 a^6 a^10 a^11 a a^12 a^14 a^5 a^8 a^7 a^4 a^2 ] ]

</Example>
<!--
F:=GF(16);
a:=PrimitiveRoot(F);; b:=a^7; b^4+b^3+1; 
Pts:=List([0..14],i->b^i);
x:=X(F);;
R1:=PolynomialRing(F,[x]);;
vars:=IndeterminatesOfPolynomialRing(R1);;
y:=X(F,vars);;
R2:=PolynomialRing(F,[x,y]);;
C:=GeneralizedReedSolomonCode(Pts,3,R1); 
MinimumDistance(C); 
z:=Zero(F);
r:=[z,z,z,z,z,z,z,z,b^6,b^2,b^5,b^14,b,b^7,b^11];; 
r:=Codeword(r);
cs:=NearestNeighborDecodewords(C,r,7);
-->

<ManSection>
<Func Name="Syndrome" Arg=" C v "/>

<Description>
<C>Syndrome</C> returns the syndrome of word <A>v</A>
with respect to a linear code <A>C</A>. <A>v</A> is a codeword in the 
ambient vector space of <A>C</A>.  If <A>v</A> is an element of
<A>C</A>, the syndrome is a zero vector. The syndrome can be used for looking
up an error vector in the syndrome table (see  
<Ref Func="SyndromeTable" Style="Number"/>) that is
needed to correct an error in <M>v</M>.
<P/>
A syndrome is not defined for non-linear codes. 
<C>Syndrome</C> then returns an error.
</Description>
</ManSection>

<Example>
gap> C := HammingCode(4);
a linear [15,11,3]1 Hamming (4,2) code over GF(2)
gap> v := CodewordNr( C, 7 );
[ 1 1 0 0 0 0 0 0 0 0 0 0 1 1 0 ]
gap> Syndrome( C, v );
[ 0 0 0 0 ]
gap> Syndrome( C, Codeword( "000000001100111" ) );
[ 1 1 1 1 ]
gap> Syndrome( C, Codeword( "000000000000001" ) );
[ 1 1 1 1 ]    # the same syndrome: both codewords are in the same
               # coset of C 
</Example>
<!--
C := HammingCode(4);
v := CodewordNr( C, 7 );
Syndrome( C, v );
Syndrome( C, Codeword( "000000001100111" ) );
Syndrome( C, Codeword( "000000000000001" ) );
-->

<ManSection>
<Func Name="SyndromeTable" Arg=" C "/>

<Description>
<C>SyndromeTable</C> returns a <E>syndrome table</E> of
a linear code <A>C</A>,
consisting of two columns. The first column consists of the error vectors
that correspond  to the  syndrome  vectors  in the  second column.  These
vectors both are of the codeword type. After calculating the syndrome of
a word <A>v</A>  with <C>Syndrome</C> (see 
<Ref Func="Syndrome" Style="Number"/>), 
the error vector needed to
correct <A>v</A> can be found in the syndrome table. Subtracting this vector
from <A>v</A> yields an element of <A>C</A>. 
To make the search for the syndrome as
fast as possible, the syndrome table  is sorted according to the syndrome
vectors.
</Description>
</ManSection>
<Index>syndrome table</Index>

<Example>
gap> H := HammingCode(2);
a linear [3,1,3]1 Hamming (2,2) code over GF(2)
gap> SyndromeTable(H);
[ [ [ 0 0 0 ], [ 0 0 ] ], [ [ 1 0 0 ], [ 0 1 ] ],
  [ [ 0 1 0 ], [ 1 0 ] ], [ [ 0 0 1 ], [ 1 1 ] ] ]
gap> c := Codeword("101");
[ 1 0 1 ]
gap> c in H;
false          # c is not an element of H
gap> Syndrome(H,c);
[ 1 0 ]        # according to the syndrome table,
               # the error vector [ 0 1 0 ] belongs to this syndrome
gap> c - Codeword("010") in H;
true           # so the corrected codeword is
               # [ 1 0 1 ] - [ 0 1 0 ] = [ 1 1 1 ],
               # this is an element of H 
</Example>
<!--
H := HammingCode(2);
SyndromeTable(H);
c := Codeword("101");
c in H;
Syndrome(H,c);
c - Codeword("010") in H;
-->

<ManSection>
<Func Name="StandardArray" Arg=" C "/>

<Description>
<C>StandardArray</C> returns the standard array of a 
code <A>C</A>. This is a matrix with elements of the codeword type. 
It has  <M>q^r</M> rows and <M>q^k</M> columns,  
where <M>q</M> is the size of the base field of <A>C</A>, 
<M>r=n-k</M> is the redundancy of <A>C</A>, and <M>k</M> 
is the dimension of <A>C</A>.  The first row contains all the 
elements of <A>C</A>.  Each other row contains words that do
not belong to  the code, with in the first column their syndrome vector
(see 
<Ref Func="Syndrome" Style="Number"/>).
<P/>
A non-linear code does not have a standard array. 
<C>StandardArray</C> then returns an error.
<P/>
Note that calculating a standard array can be very time- and memory-
consuming.
</Description>
</ManSection>

<Example>
gap> StandardArray(RepetitionCode(3)); 
[ [ [ 0 0 0 ], [ 1 1 1 ] ], [ [ 0 0 1 ], [ 1 1 0 ] ], 
  [ [ 0 1 0 ], [ 1 0 1 ] ], [ [ 1 0 0 ], [ 0 1 1 ] ] ]
</Example>

<ManSection>
<Func Name="PermutationDecode" Arg=" C v "/>

<Description>
<C>PermutationDecode</C> performs permutation decoding when possible
and returns original vector and prints 'fail' when not possible.
<P/>
This uses <C>AutomorphismGroup</C> in the binary case, and
(the slower) <C>PermutationAutomorphismGroup</C> otherwise, to compute
the permutation automorphism group <M>P</M> of <A>C</A>.
The algorithm runs through the elements <M>p</M> of <M>P</M>
checking if the weight of <M>H(p\cdot v)</M>
is less than <M>(d-1)/2</M>. If it is then
the vector <M>p\cdot v</M> is used to decode <M>v</M>:
assuming <A>C</A> is in standard form then 
<M>c=p^{-1}Em</M> is the decoded word, where <M>m</M>
is the information digits part of <M>p\cdot v</M>.
If no such <M>p</M> exists then ``fail'' is returned.
See, for example, section 10.2 of 
Huffman and Pless <Cite Key="HP03"/> for more details.
</Description>
</ManSection>

<Example>
gap> C0:=HammingCode(3,GF(2));
a linear [7,4,3]1 Hamming (3,2) code over GF(2)
gap> G0:=GeneratorMat(C0);;
gap> G := List(G0, ShallowCopy);;
gap> PutStandardForm(G);
()
gap> Display(G);
 1 . . . . 1 1
 . 1 . . 1 . 1
 . . 1 . 1 1 .
 . . . 1 1 1 1
gap> H0:=CheckMat(C0);;
gap> Display(H0);
 . . . 1 1 1 1
 . 1 1 . . 1 1
 1 . 1 . 1 . 1
gap> c0:=Random(C0);
[ 0 0 0 1 1 1 1 ]
gap> v01:=c0[1]+Z(2)^2;;
gap> v1:=List(c0, ShallowCopy);;
gap> v1[1]:=v01;;
gap> v1:=Codeword(v1);
[ 1 0 0 1 1 1 1 ]
gap> c1:=PermutationDecode(C0,v1);
[ 0 0 0 1 1 1 1 ]
gap> c1=c0;
true
</Example>
<!--
C0:=HammingCode(3,GF(2));
G0:=GeneratorMat(C0);;
G := List(G0, ShallowCopy);;
PutStandardForm(G);
Display(G);
H0:=CheckMat(C0);;
Display(H0);
c0:=Random(C0);
v01:=c0[1]+Z(2)^2;;
v1:=List(c0, ShallowCopy);;
v1[1]:=v01;;
v1:=Codeword(v1);
c1:=PermutationDecode(C0,v1);
c1=c0;
-->



<ManSection>
<Func Name="PermutationDecodeNC" Arg=" C v P  "/>

<Description>
Same as <C>PermutationDecode</C> except that one may enter
the permutation automorphism group <A>P</A> in as an
argument, saving time.
Here <A>P</A> is a subgroup of the
symmetric group on <M>n</M> letters,
where <M>n</M> is the word length of <A>C</A>.

</Description>
</ManSection>


</Section>
</Chapter>


<Chapter>
<Heading>Generating Codes</Heading>
<Label Name="Generating Codes"/>

In this chapter we describe functions for generating codes.
<P/>
Section 
<Ref Label="Generating Unrestricted Codes" Style="Number"/> 
describes functions for generating unrestricted codes.
<P/>
Section
<Ref Label="Generating Linear Codes" Style="Number"/> 
describes functions for generating linear
codes.
<P/>
Section
<Ref Label="Gabidulin Codes" Style="Number"/> 
describes functions for constructing certain
covering codes, such as the Gabidulin codes.
<P/>
Section
<Ref Label="Golay Codes" Style="Number"/> 
describes functions for constructing the Golay codes.
<P/>
Section
<Ref Label="Generating Cyclic Codes" Style="Number"/> 
describes functions for generating cyclic codes.
<P/>
Section
<Ref Label="Evaluation Codes" Style="Number"/> 
describes functions for generating codes as the image
of an evaluation map applied to a space of functions.
For example, generalized Reed-Solomon codes and toric codes
are described there.
<P/>
Section
<Ref Label="Algebraic geometric codes" Style="Number"/>
describes functions for generating algebraic geometry codes.
<P/>
Section
<Ref Label="LDPC" Style="Number"/>
describes functions for constructing low-density parity-check (LDPC)
codes.


<Section>
<Heading>
Generating Unrestricted Codes
</Heading>
<Label Name="Generating Unrestricted Codes"/>

In this section we start with functions that creating code from user
defined matrices or special matrices (see 
<Ref Func="ElementsCode" Style="Number"/>, 
<Ref Func="HadamardCode" Style="Number"/>,
<Ref Func="ConferenceCode" Style="Number"/>  and  
<Ref Func="MOLSCode" Style="Number"/>).   These codes are
unrestricted codes; they may later be discovered to be linear or cyclic.
<P/>
The next functions generate  random  codes  (see  
<Ref Func="RandomCode" Style="Number"/>)  and  the
Nordstrom-Robinson code (see 
<Ref Func="NordstromRobinsonCode" Style="Number"/>), respectively.
<P/>
Finally, we describe two functions for generating Greedy codes. These are
codes  that  contructed by gathering codewords from a space (see
<Ref Func="GreedyCode" Style="Number"/> and 
<Ref Func="LexiCode" Style="Number"/>).

<ManSection>
<Func Name="ElementsCode" Arg=" L [name] F "/>


<Description>
<C>ElementsCode</C> creates an unrestricted code of the 
list of elements <A>L</A>, in the field <A>F</A>. 
<A>L</A> must be a list of vectors, strings, polynomials or
codewords. <A>name</A> can contain a short description of the code.
<P/>
If <A>L</A>  contains a codeword more than once, it is removed from the list
and a GAP set is returned.
</Description>
</ManSection>

<Example>
gap> M := Z(3)^0 * [ [1, 0, 1, 1], [2, 2, 0, 0], [0, 1, 2, 2] ];;
gap> C := ElementsCode( M, "example code", GF(3) );
a (4,3,1..4)2 example code over GF(3)
gap> MinimumDistance( C );
4
gap> AsSSortedList( C );
[ [ 0 1 2 2 ], [ 1 0 1 1 ], [ 2 2 0 0 ] ]
</Example>
<!--
M := Z(3)^0 * [ [1, 0, 1, 1], [2, 2, 0, 0], [0, 1, 2, 2] ];;
C := ElementsCode( M, "example code", GF(3) );
MinimumDistance( C );
AsSSortedList( C );
-->

<Index>
code, Hadamard
</Index>

<ManSection>
<Func Name="HadamardCode" Arg=" H [t] "/>


<Description>
The four forms this command can take are
<C>HadamardCode(H,t)</C>, <C>HadamardCode(H)</C>,
<C>HadamardCode(n,t)</C>, and <C>HadamardCode(n)</C>.
<P/>
In the case when the arguments <A>H</A> and <A>t</A> are both given,
<C>HadamardCode</C> returns a Hadamard code 
of the <M>t^{th}</M> kind from the Hadamard matrix <A>H</A>
In case only <A>H</A> is given, <M>t = 3</M> is used.
<P/>
By definition, a Hadamard matrix is a square matrix <A>H</A> with 
<M>H\cdot H^T = -n\cdot I_n</M>, where <M>n</M> is the size of 
<A>H</A>. The entries of <A>H</A> are either 1 or -1.
<Index>Hadamard matrix</Index>
<P/>
The matrix <A>H</A> is first transformed into a binary matrix 
<M>A_n</M> by replacing the <M>1</M>'s by <M>0</M>'s and 
the <M>-1</M>'s by <M>1</M>s).
<P/>
The Hadamard matrix of the <E>first kind</E> (<M>t=1</M>) is 
created by using the rows of <M>A_n</M> as elements,
after deleting the first column. This is a 
<M>(n-1, n,  n/2)</M> code.  We use this code for creating the 
Hadamard code of the <E>second kind</E> (<M>t=2</M>), by
adding all the complements of the already existing codewords. This
results in a <M>(n-1, 2n, n/2 -1)</M> code.  
The <E>third kind</E> (<M>t=3</M>) is created
by using the rows of <M>A_n</M> (without cutting a column) and their
complements as elements.  This way, we have an 
<M>(n, 2n, n/2)</M>-code.  The
returned code is generally an unrestricted code, but for <M>n = 2^r</M>, 
the code is linear.
<P/>
The command <C>HadamardCode(n,t)</C> returns a Hadamard code with parameter
<A>n</A> of the <M>t^{th}</M> kind. For the
command <C>HadamardCode(n)</C>, <M>t=3</M> is used.
<P/>
When called in these forms, <C>HadamardCode</C> first creates a Hadamard
matrix (see  <Ref Func="HadamardMat" Style="Number"/>), of size 
<A>n</A> and then follows the same
procedure as described above.  Therefore the same restrictions with
respect to <A>n</A> as for Hadamard matrices hold.
</Description>
</ManSection>

<Example>
gap> H4 := [[1,1,1,1],[1,-1,1,-1],[1,1,-1,-1],[1,-1,-1,1]];;
gap> HadamardCode( H4, 1 );
a (3,4,2)1 Hadamard code of order 4 over GF(2)
gap> HadamardCode( H4, 2 );
a (3,8,1)0 Hadamard code of order 4 over GF(2)
gap> HadamardCode( H4 );
a (4,8,2)1 Hadamard code of order 4 over GF(2) 
gap> H4 := [[1,1,1,1],[1,-1,1,-1],[1,1,-1,-1],[1,-1,-1,1]];;
gap> C := HadamardCode( 4 );
a (4,8,2)1 Hadamard code of order 4 over GF(2)
gap> C = HadamardCode( H4 );
true 
</Example>
<!--
H4 := [[1,1,1,1],[1,-1,1,-1],[1,1,-1,-1],[1,-1,-1,1]];;
HadamardCode( H4, 1 );
HadamardCode( H4, 2 );
HadamardCode( H4 );
H4 := [[1,1,1,1],[1,-1,1,-1],[1,1,-1,-1],[1,-1,-1,1]];;
C := HadamardCode( 4 );
C = HadamardCode( H4 );
-->

<Index>
code, conference
</Index>

<ManSection>
<Func Name="ConferenceCode" Arg=" H "/>

<Description>
<C>ConferenceCode</C> returns a code of length <M>n-1</M> constructed from a
symmetric 'conference matrix' <A>H</A>. A <E>conference matrix</E> 
<A>H</A> is a symmetric matrix of
order <M>n</M>, which satisfies <M>H\cdot H^T = ((n-1)\cdot I</M>, with 
<M>n \equiv  2 \pmod 4</M>. The rows of <M>\frac{1}{2}(H+I+J)</M>, 
<M>\frac{1}{2}(-H+I+J)</M>,  plus the zero and all-ones vectors
form the elements of a binary non-linear <M>(n-1,  2n, (n-2)/2)</M>
code.
<Index>conference matrix</Index>
<P/>
<Package>GUAVA</Package> constructs a symmetric conference 
matrix of order <M>n+1</M> (<M>n\equiv 1 \pmod 4</M>) and uses
the rows of that matrix, plus the zero and
all-ones vectors, to construct a binary non-linear 
<M>(n, 2(n+1), (n-1)/2)</M>-code.
</Description>
</ManSection>

<Example>
gap> H6 := [[0,1,1,1,1,1],[1,0,1,-1,-1,1],[1,1,0,1,-1,-1],
> [1,-1,1,0,1,-1],[1,-1,-1,1,0,1],[1,1,-1,-1,1,0]];;
gap> C1 := ConferenceCode( H6 );
a (5,12,2)1..4 conference code over GF(2)
gap> IsLinearCode( C1 );
false 
gap> C2 := ConferenceCode( 5 );
a (5,12,2)1..4 conference code over GF(2)
gap> AsSSortedList( C2 );
[ [ 0 0 0 0 0 ], [ 0 0 1 1 1 ], [ 0 1 0 1 1 ], [ 0 1 1 0 1 ], [ 0 1 1 1 0 ], 
  [ 1 0 0 1 1 ], [ 1 0 1 0 1 ], [ 1 0 1 1 0 ], [ 1 1 0 0 1 ], [ 1 1 0 1 0 ], 
  [ 1 1 1 0 0 ], [ 1 1 1 1 1 ] ]
</Example>
<!--
H6 := [[0,1,1,1,1,1],[1,0,1,-1,-1,1],[1,1,0,1,-1,-1],
 [1,-1,1,0,1,-1],[1,-1,-1,1,0,1],[1,1,-1,-1,1,0]];;
C1 := ConferenceCode( H6 );
IsLinearCode( C1 );
C2 := ConferenceCode( 5 );
AsSSortedList( C2 );
-->


<ManSection>
<Func Name="MOLSCode" Arg=" [n] q "/>

<Description>
<C>MOLSCode</C> returns an <M>(n, q^2, n-1)</M> code over <M>GF(q)</M>. 
The code is created from <M>n-2</M> 'Mutually Orthogonal Latin Squares' 
(MOLS) of size <M>q \times q</M>. The default for <A>n</A> is <M>4</M>. 
<Package>GUAVA</Package> can construct a MOLS code for
<M>n-2 \leq q</M>. Here <A>q</A> must be a prime power, <M>q  > 2</M>. 
If there are no <M>n-2</M> MOLS, an error is signalled.
<P/>
Since each of the <M>n-2</M> MOLS is a <M>q\times q</M> matrix, we can create a code
of size <M>q^2</M> by listing in each code element the entries that are in the
same position in each of the MOLS.  We precede each of these lists with
the two  coordinates that specify this position, making the word length
become <M>n</M>.
<P/>
The MOLS codes are MDS codes (see <Ref Func="IsMDSCode" Style="Number"/>).
</Description>
</ManSection>

<Example>
gap> C1 := MOLSCode( 6, 5 );
a (6,25,5)3..4 code generated by 4 MOLS of order 5 over GF(5)
gap> mols := List( [1 .. WordLength(C1) - 2 ], function( nr )
>       local ls, el;
>       ls := NullMat( Size(LeftActingDomain(C1)), Size(LeftActingDomain(C1)) );
>       for el in VectorCodeword( AsSSortedList( C1 ) ) do
>          ls[IntFFE(el[1])+1][IntFFE(el[2])+1] := el[nr + 2];
>       od;
>       return ls;
>    end );;
gap> AreMOLS( mols );
true
gap> C2 := MOLSCode( 11 );
a (4,121,3)2 code generated by 2 MOLS of order 11 over GF(11) 
</Example>
<!--
C1 := MOLSCode( 6, 5 );
mols := List( [1 .. WordLength(C1) - 2 ], function( nr )
    local ls, el;
    ls := NullMat( Size(LeftActingDomain(C1)), Size(LeftActingDomain(C1)) );
    for el in VectorCodeword( AsSSortedList( C1 ) ) do
          ls[IntFFE(el[1])+1][IntFFE(el[2])+1] := el[nr + 2];
    od;
  return ls;
end );;
AreMOLS( mols );
C2 := MOLSCode( 11 );
-->

<ManSection>
<Func Name="RandomCode" Arg=" n M F "/>

<Description>
<C>RandomCode</C> returns a random unrestricted code of size 
<A>M</A> with word length <A>n</A> over <A>F</A>. <A>M</A> must be 
less than or equal to the number of elements in the space <M>GF(q)^n</M>.
<P/>
The function <C>RandomLinearCode</C> returns a random linear code (see
<Ref Func="RandomLinearCode" Style="Number"/>). 
</Description>
</ManSection>

<Example>
gap> C1 := RandomCode( 6, 10, GF(8) );
a (6,10,1..6)4..6 random unrestricted code over GF(8)
gap> MinimumDistance(C1);
3
gap> C2 := RandomCode( 6, 10, GF(8) );
a (6,10,1..6)4..6 random unrestricted code over GF(8)
gap> C1 = C2;
false 
</Example>

<Index>
code, Nordstrom-Robinson
</Index>

<ManSection>
<Func Name="NordstromRobinsonCode" Arg=" "/>

<Description>
<C>NordstromRobinsonCode</C> returns a Nordstrom-Robinson code, 
the best code with word length <M>n=16</M> and minimum distance 
<M>d=6</M> over <M>GF(2)</M>. This is a non-linear <M>(16, 256, 6)</M>
code.
</Description>
</ManSection>

<Example>
gap> C := NordstromRobinsonCode();
a (16,256,6)4 Nordstrom-Robinson code over GF(2)
gap> OptimalityCode( C );
0 
</Example>


<Index>
code, greedy
</Index>

<ManSection>
<Func Name="GreedyCode" Arg=" L d F "/>

<Description>
<C>GreedyCode</C> returns a Greedy code with design distance 
<A>d</A> over the finite field <A>F</A>. The
code is  constructed using the greedy algorithm on the list of vectors
<A>L</A>. (The greedy algorithm checks each vector in <A>L</A> and 
adds it to the code if its distance to the current 
code is greater than  or equal to <A>d</A>. It is
obvious that the resulting code has a minimum distance of 
at least <A>d</A>.
<P/>
Greedy codes are often linear codes.
<P/>
The function <C>LexiCode</C> creates a greedy code from a basis instead of an
enumerated list (see <Ref Func="LexiCode" Style="Number"/>).
</Description>
</ManSection>

<Example>
gap> C1 := GreedyCode( Tuples( AsSSortedList( GF(2) ), 5 ), 3, GF(2) );
a (5,4,3..5)2 Greedy code, user defined basis over GF(2)
gap> C2 := GreedyCode( Permuted( Tuples( AsSSortedList( GF(2) ), 5 ),
>                         (1,4) ), 3, GF(2) );
a (5,4,3..5)2 Greedy code, user defined basis over GF(2)
gap> C1 = C2;
false 
</Example>
<!--
C1 := GreedyCode( Tuples( AsSSortedList( GF(2) ), 5 ), 3, GF(2) );
C2 := GreedyCode( Permuted(Tuples(AsSSortedList(GF(2)),5), (1,4)), 3, GF(2) );
C1 = C2;
-->


<ManSection>
<Func Name="LexiCode" Arg=" n d F "/>

<Description>
In this format, <C>Lexicode</C> returns a lexicode with word length 
<A>n</A>, design distance <A>d</A> over <A>F</A>. 
The code is  constructed using  the greedy algorithm on the 
lexicographically ordered  list of all vectors of length
<A>n</A> over <A>F</A>. Every time a vector is found that has a distance 
to the current code of at least <A>d</A>,  it is added to the 
code. This results, obviously, in a code with minimum distance 
greater than or equal to <A>d</A>.
<P/>
Another syntax which one can use is <C>LexiCode( B, d, F )</C>.
When called in this format, <C>LexiCode</C> uses the basis <A>B</A> 
instead of the standard basis. <A>B</A> is a matrix of vectors
over <A>F</A>.  The code is constructed using the greedy 
algorithm on the list of vectors spanned by
<A>B</A>, ordered lexicographically with respect to <A>B</A>.
<P/>
Note that binary lexicodes are always linear.
</Description>
</ManSection>

<Example>
gap> C := LexiCode( 4, 3, GF(5) );
a (4,17,3..4)2..4 lexicode over GF(5) 
gap> B := [ [Z(2)^0, 0*Z(2), 0*Z(2)], [Z(2)^0, Z(2)^0, 0*Z(2)] ];;
gap> C := LexiCode( B, 2, GF(2) );
a linear [3,1,2]1..2 lexicode over GF(2) 
</Example>

The function <C>GreedyCode</C> creates a greedy code that is not restricted to
a lexicographical order (see <Ref Func="GreedyCode" Style="Number"/>).

</Section>

<Section>
<Heading>
Generating Linear Codes
</Heading>
<Label Name="Generating Linear Codes"/>

In this section we describe functions for constructing linear codes.  A
linear code always has a generator or check matrix.
<P/>
The first two functions generate linear codes from the  generator  matrix
(<Ref Func="GeneratorMatCode" Style="Number"/>) or check matrix 
(<Ref Func="CheckMatCode" Style="Number"/>). All  linear  codes
can be constructed with these functions.
<P/>
The next functions we describe  generate  some  well-known  codes,  like
Hamming codes (<Ref Func="HammingCode" Style="Number"/>), 
Reed-Muller codes  (<Ref Func="ReedMullerCode" Style="Number"/>) 
and the extended Golay codes 
(<Ref Func="ExtendedBinaryGolayCode" Style="Number"/> and
<Ref Func="ExtendedTernaryGolayCode" Style="Number"/>).
<P/>
A large and powerful family of codes are alternant codes.  They are
obtained by a small modification of the parity check matrix of a BCH code
(see <Ref Func="AlternantCode" Style="Number"/>, 
<Ref Func="GoppaCode" Style="Number"/>,
<Ref Func="GeneralizedSrivastavaCode" Style="Number"/> and 
<Ref Func="SrivastavaCode" Style="Number"/>).
<P/>
Finally, we describe a function for generating random linear codes (see
<Ref Func="RandomLinearCode" Style="Number"/>).
<P/>

<ManSection>
<Func Name="GeneratorMatCode" Arg=" G [name] F "/>

<Description>
<C>GeneratorMatCode</C> returns a linear code with generator matrix 
<A>G</A>. <A>G</A> must be a matrix over finite field <A>F</A>. 
<A>name</A> can contain a short description of the code.  
The generator matrix is the basis of the
elements of the code. The resulting code has word length 
<M>n</M>, dimension <M>k</M> if <A>G</A> is a <M>k \times n</M>-matrix. 
If <M>GF(q)</M> is the field of the code, the
size of the code will be <M>q^k</M>.
<P/>
If the generator matrix does not have full row rank, the linearly
dependent rows are removed. This is  done by the GAP
function <C>BaseMat</C>  and results in an equal code. 
The generator matrix can be retrieved with the function 
<C>GeneratorMat</C> (see <Ref Func="GeneratorMat" Style="Number"/>).
</Description>
</ManSection>

<Example>
gap> G := Z(3)^0 * [[1,0,1,2,0],[0,1,2,1,1],[0,0,1,2,1]];;
gap> C1 := GeneratorMatCode( G, GF(3) );
a linear [5,3,1..2]1..2 code defined by generator matrix over GF(3)
gap> C2 := GeneratorMatCode( IdentityMat( 5, GF(2) ), GF(2) );
a linear [5,5,1]0 code defined by generator matrix over GF(2)
gap> GeneratorMatCode( List( AsSSortedList( NordstromRobinsonCode() ),
> x -> VectorCodeword( x ) ), GF( 2 ) );
a linear [16,11,1..4]2 code defined by generator matrix over GF(2)
# This is the smallest linear code that contains the N-R code 
</Example>
<!--
G := Z(3)^0 * [[1,0,1,2,0],[0,1,2,1,1],[0,0,1,2,1]];;
C1 := GeneratorMatCode( G, GF(3) );
C2 := GeneratorMatCode( IdentityMat( 5, GF(2) ), GF(2) );
GeneratorMatCode(List(AsSSortedList(NordstromRobinsonCode()),x ->VectorCodeword(x)),GF(2));
-->

<ManSection>
<Func Name="CheckMatCodeMutable" Arg=" H [name] F "/>

<Description>
<C>CheckMatCodeMutable</C> is the same as 
<C>CheckMatCode</C> except that the check matrix and generator
matrix are mutable.
</Description>
</ManSection>

<ManSection>
<Func Name="CheckMatCode" Arg=" H [name] F "/>

<Description>
<C>CheckMatCode</C> returns a linear code with check matrix 
<A>H</A>. <A>H</A> must be a matrix over Galois field <A>F</A>. 
<A>[name.</A> can contain a short description of
the code. The parity check matrix is the transposed of the nullmatrix of
the generator matrix of the code. Therefore, 
<M>c\cdot H^T =  0</M> where <M>c</M> is an element of the code.  
If <A>H</A> is a <M>r\times n</M>-matrix, the code has word
length <M>n</M>, redundancy <M>r</M> and dimension <M>n-r</M>.
<P/>
If the check matrix does not have full row rank, the linearly dependent
rows are removed. This is done by the GAP function <C>BaseMat</C>.
and results in an equal code. The check matrix can be retrieved with the
function 
<C>CheckMat</C> (see <Ref Func="CheckMat" Style="Number"/>).
</Description>
</ManSection>

<Example>
gap> G := Z(3)^0 * [[1,0,1,2,0],[0,1,2,1,1],[0,0,1,2,1]];;
gap> C1 := CheckMatCode( G, GF(3) );
a linear [5,2,1..2]2..3 code defined by check matrix over GF(3)
gap> CheckMat(C1);
[ [ Z(3)^0, 0*Z(3), Z(3)^0, Z(3), 0*Z(3) ],
  [ 0*Z(3), Z(3)^0, Z(3), Z(3)^0, Z(3)^0 ],
  [ 0*Z(3), 0*Z(3), Z(3)^0, Z(3), Z(3)^0 ] ]
gap> C2 := CheckMatCode( IdentityMat( 5, GF(2) ), GF(2) );
a cyclic [5,0,5]5 code defined by check matrix over GF(2)
</Example>
<!--
G := Z(3)^0 * [[1,0,1,2,0],[0,1,2,1,1],[0,0,1,2,1]];;
C1 := CheckMatCode( G, GF(3) );
CheckMat(C1);
C2 := CheckMatCode( IdentityMat( 5, GF(2) ), GF(2) );
-->

<Index>
code, Hamming
</Index>

<ManSection>
<Func Name="HammingCode" Arg=" r F "/>

<Description>
<C>HammingCode</C> returns a Hamming code with redundancy 
<A>r</A>  over <A>F</A>.  A Hamming code is a single-error-correcting 
code. The parity check matrix of a Hamming code has all nonzero vectors
of length <A>r</A> in its columns,
except for a multiplication factor. The decoding algorithm of the Hamming
code (see <Ref Func="Decode" Style="Number"/>) makes use of this property.
<P/>
If <M>q</M> is the size of its field <A>F</A>, the returned 
Hamming code is a linear <M>[(q^r-1)/(q-1), (q^r-1)/(q-1) - r, 3]</M> code.
</Description>
</ManSection>

<Example>
gap> C1 := HammingCode( 4, GF(2) );
a linear [15,11,3]1 Hamming (4,2) code over GF(2)
gap> C2 := HammingCode( 3, GF(9) );
a linear [91,88,3]1 Hamming (3,9) code over GF(9) 
</Example>
<!--
C1 := HammingCode( 4, GF(2) );
C2 := HammingCode( 3, GF(9) );
-->

<Index>
code, Reed-Muller
</Index>

<ManSection>
<Func Name="ReedMullerCode" Arg=" r k "/>

<Description>
<C>ReedMullerCode</C> returns a binary 'Reed-Muller code' 
<A>R(r, k)</A>  with dimension <A>k</A> and order <A>r</A>. 
This is a code with length <M>2^k</M> and
minimum  distance <M>2^{k-r}</M> (see for example,
section 1.10 in <Cite Key="HP03"/>). By definition, the <M>r^{th}</M>
order binary Reed-Muller code of length <M>n=2^m</M>, for 
<M>0 \leq r \leq m</M>, is the set of all vectors <M>f</M>, where 
<M>f</M> is a Boolean function which is a polynomial of degree 
at most <M>r</M>.
</Description>
</ManSection>

<Example>
gap> ReedMullerCode( 1, 3 );
a linear [8,4,4]2 Reed-Muller (1,3) code over GF(2) 
</Example>
<!--
ReedMullerCode( 1, 3 );

############# insert more examples #############
-->

See <Ref Func="GeneralizedReedMullerCode" Style="Number"/>
for a more general construction.

<Index>
code, alternant
</Index>

<ManSection>
<Func Name="AlternantCode" Arg=" r Y [alpha] F "/>

<Description>
<C>AlternantCode</C> returns an 'alternant code', 
with parameters <A>r</A>, <A>Y</A> and
<A>alpha</A> (optional).  <A>F</A> denotes the (finite) base field.
Here, <A>r</A> is the design redundancy of the code. <A>Y</A> and
<A>alpha</A> are both vectors of length <A>n</A> from which 
the parity check matrix is constructed. 
The check matrix has the form <M>H=([a_i^j y_i])</M>,
where <M>0 \leq j\leq r-1</M>, <M>1 \leq i\leq n</M>,
and where <M>[...]</M>
is as in <Ref Func="VerticalConversionFieldMat" Style="Number"/>).
If no <A>alpha</A> is specified, the vector 
<M>[1, a,  a^2, .., a^{n-1}]</M> is used,
where <M>a</M> is a primitive element of a Galois field <A>F</A>.
</Description>
</ManSection>

<Example>
gap> Y := [ 1, 1, 1, 1, 1, 1, 1];; a := PrimitiveUnityRoot( 2, 7 );;
gap> alpha := List( [0..6], i -> a^i );;
gap> C := AlternantCode( 2, Y, alpha, GF(8) );
a linear [7,3,3..4]3..4 alternant code over GF(8) 
</Example>
<!--
Y := [ 1, 1, 1, 1, 1, 1, 1];; a := PrimitiveUnityRoot( 2, 7 );;
alpha := List( [0..6], i -> a^i );;
C := AlternantCode( 2, Y, alpha, GF(8) );
-->

<Index>
code, Goppa (classical)
</Index>

<ManSection>
<Func Name="GoppaCode" Arg=" G L "/>

<Description>
<C>GoppaCode</C> returns a Goppa code <A>C</A> from Goppa polynomial 
<A>g</A>, having coefficients in a Galois Field <M>GF(q)</M>. 
<A>L</A> must  be a list of elements in <M>GF(q)</M>, 
that are not roots of <A>g</A>.  The word length of the code is
equal to the length of <A>L</A>. The parity check matrix has the
form <M>H=([a_i^j /  G(a_i)])_{0 \leq j \leq deg(g)-1,\ a_i \in L}</M>, 
where <M>a_i\in L</M>
and <M>[...]</M> is as in 
<Ref Func="VerticalConversionFieldMat" Style="Number"/>,
so <M>H</M> has entries in <M>GF(q)</M>, <M>q=p^m</M>.
It is known that <M>d(C)\geq deg(g)+1</M>, with a better
bound in the binary case provided <M>g</M> has no 
multiple roots. See Huffman and Pless
<Cite Key="HP03"/> section 13.2.2, and
MacWilliams and Sloane <Cite Key="MS83"/> section 12.3,
for more details.
<P/>
One can also call <C>GoppaCode</C> using the syntax
<C>GoppaCode(g,n)</C>. 
When called with parameter <A>n</A>, 
<Package>GUAVA</Package> constructs a list <M>L</M> of length
<A>n</A>, such that no element of <A>L</A> is a root of <A>g</A>.
<P/>
This is a special case of an alternant code.
</Description>
</ManSection>

<Example>
gap> x:=Indeterminate(GF(8),"x");
x
gap> L:=Elements(GF(8));
[ 0*Z(2), Z(2)^0, Z(2^3), Z(2^3)^2, Z(2^3)^3, Z(2^3)^4, Z(2^3)^5, Z(2^3)^6 ]
gap> g:=x^2+x+1;
x^2+x+Z(2)^0
gap> C:=GoppaCode(g,L);
a linear [8,2,5]3 Goppa code over GF(2)
gap> xx := Indeterminate( GF(2), "xx" );; 
gap> gg := xx^2 + xx + 1;; L := AsSSortedList( GF(8) );;
gap> C1 := GoppaCode( gg, L );
a linear [8,2,5]3 Goppa code over GF(2) 
gap> y := Indeterminate( GF(2), "y" );; 
gap> h := y^2 + y + 1;;
gap> C2 := GoppaCode( h, 8 );
a linear [8,2,5]3 Goppa code over GF(2) 
gap> C1=C2;
true
gap> C=C1;
true
</Example>
<!-- 
x:=Indeterminate(GF(8),"x");
L:=Elements(GF(8));
g:=x^2+x+1;
C:=GoppaCode(g,L);
xx := Indeterminate( GF(2), "xx" );; 
gg := xx^2 + xx + 1;; L := AsSSortedList( GF( 8) );;
C1 := GoppaCode( gg, L );
y := Indeterminate( GF(2), "y" );; 
h := y^2 + y + 1;;
C2 := GoppaCode( h, 8 );
C1=C2; 
C=C1;
-->

<Index>
code, Srivastava
</Index>

<ManSection>
<Func Name="GeneralizedSrivastavaCode" Arg=" a w z [t] F "/>

<Description>
<C>GeneralizedSrivastavaCode</C> returns a generalized Srivastava
code with parameters <A>a</A>, <A>w</A>, <A>z</A>, 
<A>t</A>. <M>a =\{ a_1, ..., a_n\}</M> and 
<M>w =\{ w_1, ..., w_s\}</M> are lists of <M>n+s</M> 
distinct elements of <M>F=GF(q^m)</M>, 
<M>z</M> is a list of length <M>n</M> of nonzero elements 
of <M>GF(q^m)</M>. The parameter <A>t</A>
determines the designed distance: <M>d  \geq  st + 1</M>.  
The check matrix of this code is the form 
<Display>
H=([\frac{z_i}{(a_i - w_j)^k}]),
</Display>
<M>1\leq k\leq t</M>, where
<M>[...]</M> is as in 
<Ref Func="VerticalConversionFieldMat" Style="Number"/>.  
We use this definition of <M>H</M> to define the code.
The default for <A>t</A> is 1. 
The original Srivastava codes (see  
<Ref Func="SrivastavaCode" Style="Number"/>) are a
special case <M>t=1</M>, <M>z_i=a_i^\mu</M>, for some 
<M>\mu</M>.

</Description>
</ManSection>

<Example>
gap> a := Filtered( AsSSortedList( GF(2^6) ), e -> e in GF(2^3) );;
gap> w := [ Z(2^6) ];; z := List( [1..8], e -> 1 );;
gap> C := GeneralizedSrivastavaCode( a, w, z, 1, GF(64) );
a linear [8,2,2..5]3..4 generalized Srivastava code over GF(2) 
</Example>
<!--
a := Filtered( AsSSortedList( GF(2^6) ), e -> e in GF(2^3) );;
w := [ Z(2^6) ];; z := List( [1..8], e -> 1 );;
C := GeneralizedSrivastavaCode( a, w, z, 1, GF(64) );
-->


<ManSection>
<Func Name="SrivastavaCode" Arg=" a w [mu] F "/>

<Description>
<M>SrivastavaCode</M> returns a Srivastava code with parameters 
<A>a</A>, <A>w</A> (and optionally <A>mu</A>).
<M>a =\{ a_1, ..., a_n\}</M> and 
<M>w =\{ w_1, ..., w_s\}</M> are lists of <M>n+s</M> 
distinct elements of <M>F=GF(q^m)</M>. 
The default for <A>mu</A> is 1. The
Srivastava code is a generalized Srivastava code, 
in which <M>z_i = a_i^{mu}</M> for some <A>mu</A>
and <M>t=1</M>.
<P/>
J. N. Srivastava introduced this code in 1967,
though his work was not published. 
See Helgert <Cite Key="He72"/> for more details on the 
properties of this code. 
Related reference:
G. Roelofsen,
<B>On Goppa and Generalized Srivastava Codes</B>
PhD thesis, Dept. Math. and Comp. Sci., Eindhoven Univ. of
Technology, the Netherlands, 1982.
<!--
H. J. Helgert. <E>Noncyclic generalizations of BCH and Srivastava codes</E>. 
<B>Information and Control</B>, 21(3):280-290, October 1972. 
-->

</Description>
</ManSection>

<Example>
gap> a := AsSSortedList( GF(11) ){[2..8]};;
gap> w := AsSSortedList( GF(11) ){[9..10]};;
gap> C := SrivastavaCode( a, w, 2, GF(11) );
a linear [7,5,3]2 Srivastava code over GF(11)
gap> IsMDSCode( C );
true    # Always true if F is a prime field 
</Example>
<!--
a := AsSSortedList( GF(11) ){[2..8]};;
w := AsSSortedList( GF(11) ){[9..10]};;
C := SrivastavaCode( a, w, 2, GF(11) );
IsMDSCode( C );
# Why is this always true if F is a prime field ? 
# not in Helgert 1972 ...
-->

<Index>
code, Cordaro-Wagner
</Index>

<ManSection>
<Func Name="CordaroWagnerCode" Arg=" n "/>

<Description>
<C>CordaroWagnerCode</C> returns a binary Cordaro-Wagner code. 
This is a code of length <A>n</A> and dimension <M>2</M>
having the best possible minimum distance
<M>d</M>.  This code is just a little bit less trivial than 
<C>RepetitionCode</C>
(see <Ref Func="RepetitionCode" Style="Number"/>).

</Description>
</ManSection>

<Example>
gap> C := CordaroWagnerCode( 11 );
a linear [11,2,7]5 Cordaro-Wagner code over GF(2)
gap> AsSSortedList(C);                 
[ [ 0 0 0 0 0 0 0 0 0 0 0 ], [ 0 0 0 0 1 1 1 1 1 1 1 ], 
  [ 1 1 1 1 0 0 0 1 1 1 1 ], [ 1 1 1 1 1 1 1 0 0 0 0 ] ]
</Example>


<ManSection>
<Func Name="FerreroDesignCode" Arg=" P m "/>

<Description>
<E>Requires the GAP package SONATA</E>
<P/>
A group <M>K</M> together with a group of
automorphism <M>H</M> of <M>K</M> such that the
semidirect product <M>KH</M> is a Frobenius group with
complement <M>H</M> is called a Ferrero pair <M>(K, H)</M>
in SONATA. 
Take a Frobenius <M>(G,+)</M> group with kernel <M>K</M>
and complement <M>H</M>.
Consider the design <M>D</M> with point set <M>K</M> and block set
<M>\{ a^H + b\ |\ a, b \in K, a \not= 0 \}</M>.
Here <M>a^H</M> denotes the orbit of a under conjugation by elements
of <M>H</M>. Every planar near-ring design of type "*" can be obtained
in this way from groups. 
These designs (from a Frobenius kernel
of order <M>v</M> and a Frobenius complement of order <M>k</M>) have
<M>v(v-1)/k</M> distinct blocks and they are all of size <M>k</M>.
Moreover each of the <M>v</M> points occurs in exactly <M>v-1</M> distinct
blocks. Hence the rows and the columns of the incidence
matrix <M>M</M> of the design are always of constant weight.
<P/>
<C>FerreroDesignCode</C>
constructs binary linear code arising from the incdence
matrix of a design associated to a "Ferrero pair" arising
from a fixed-point-free (fpf) automorphism groups and Frobenius group.
<P/>
INPUT: <M>P</M> is a list of prime powers describing an abelian group <M>G</M>.
       <M>m > 0</M> is an integer such that <M>G</M> admits a cyclic fpf 
	   automorphism group of size <M>m</M>.
	   This means that for all <M>q = p^k \in P</M>,
	   OrderMod(<M>p</M>, <M>m</M>) must divide <M>q</M> 
	   (see the SONATA documentation for <C>FpfAutomorphismGroupsCyclic</C>).
<P/>
 OUTPUT: The binary linear code whose generator matrix is the
         incidence matrix of a design associated to a "Ferrero pair" arising
		 from the fixed-point-free (fpf) automorphism group of <M>G</M>.
		 The pair <M>(H,K)</M> is called a Ferraro pair and the semidirect product
		 <M>KH</M> is a Frobenius group with complement <M>H</M>.
<P/>
 AUTHORS: Peter Mayr and David Joyner

</Description>
</ManSection>

<Example>
gap> G:=AbelianGroup([5,5] );
 [ pc group of size 25 with 2 generators ]
gap> FpfAutomorphismGroupsMaxSize( G );
[ 24, 2 ]
gap> L:=FpfAutomorphismGroupsCyclic( [5,5], 3 );
[ [ [ f1, f2 ] -> [ f1*f2^2, f1*f2^3 ] ],
  [ pc group of size 25 with 2 generators ] ]
gap> D := DesignFromFerreroPair( L[2], Group(L[1][1]), "*" );
 [ a 2 - ( 25, 3, 2 ) nearring generated design ]
gap> M:=IncidenceMat( D );; Length(M); Length(TransposedMat(M));
25
200
gap> C1:=GeneratorMatCode(M*Z(2),GF(2));
a linear [200,25,1..24]62..100 code defined by generator matrix over GF(2)
gap> MinimumDistance(C1);
24
gap> C2:=FerreroDesignCode( [5,5],3);
a linear [200,25,1..24]62..100 code defined by generator matrix over GF(2)
gap> C1=C2;
true

</Example>
<!--


G:=AbelianGroup([5,5] );
FpfAutomorphismGroupsMaxSize( G );
L:=FpfAutomorphismGroupsCyclic( [5,5], 3 );
D := DesignFromFerreroPair( L[2], Group(L[1][1]), "*" );
M:=IncidenceMat( D );; Length(M); Length(TransposedMat(M));
C1:=GeneratorMatCode(M*Z(2),GF(2));
MinimumDistance(C1);
C2:=FerreroDesignCode( [5,5],3);
C1=C2;

-->



<ManSection>
<Func Name="RandomLinearCode" Arg=" n k F "/>

<Description>
<C>RandomLinearCode</C> returns a random linear code with word length 
<A>n</A>, dimension <A>k</A> over field <A>F</A>.
The method used is to first construct a
<M>k\times n</M> matrix of the block form <M>(I,A)</M>,
where <M>I</M> is a <M>k\times k</M> identity matrix
and  <M>A</M> is a <M>k\times (n-k)</M> matrix 
constructed using <C>Random(F)</C> repeatedly.
Then the columns are permuted using a randomly
selected element of <C>SymmetricGroup(n)</C>.
<P/>
To create a random unrestricted code, use <C>RandomCode</C> (see
<Ref Func="RandomCode" Style="Number"/>).
</Description>
</ManSection>

<Example>
gap> C := RandomLinearCode( 15, 4, GF(3) );
a  [15,4,?] randomly generated code over GF(3)
gap> Display(C);
a linear [15,4,1..6]6..10 random linear code over GF(3)
</Example>
<!--
C := RandomLinearCode( 15, 4, GF(3) );
Display(C);
-->

The method <Package>GUAVA</Package> chooses to output the result of a
<C>RandomLinearCode</C> command is different than other codes. 
For example, the bounds on the minimum distance is not displayed.
Howeer, you can use the <C>Display</C> command to print this information.
This new display method was added in version 1.9 to speed up
the command (if <M>n</M> is about 80 and
<M>k</M> about 40, for example, the time it took to
look up and/or calculate the bounds on the minimum distance
was too long).


<ManSection>
<Func Name="OptimalityCode" Arg=" C "/>

<Description>
<!--In general this command is no longer accurate, since the
tables have not been updated since 1998. See the web site
<URL>http://www.win.tue.nl/~aeb/voorlincod.html</URL>
for more recent data.
<P/>-->
<C>OptimalityCode</C> returns the difference between the smallest 
known upper bound and the actual size of the code. Note that the value of the
function <C>UpperBound</C> is not always equal to the actual upper bound 
<M>A(n,d)</M> thus the result may not be equal to <M>0</M> 
even if the code is optimal!
<P/>
<C>OptimalityLinearCode</C> is similar but applies only
to linear codes.
</Description>
</ManSection>


<ManSection>
<Func Name="BestKnownLinearCode" Arg=" n k F "/>

<Description>
<!--In general this command is no longer accurate, since the
tables have not been updated since 1998. See the web site
<URL>http://www.win.tue.nl/~aeb/voorlincod.html</URL>
for more recent data.
<P/>-->
<C>BestKnownLinearCode</C> returns the best known (as of 11 May 2006<!--1998-->)
linear code of length <A>n</A>,
dimension <A>k</A> over field <A>F</A>. 
The function uses the tables described in
section <Ref Func="BoundsMinimumDistance" Style="Number"/> 
to construct this code.
<P/>
This command can also be called using the syntax
<C>BestKnownLinearCode( rec )</C>, where
<A>rec</A> must be a record containing the fields `lowerBound',
`upperBound' and `construction'. It uses the information in this field to
construct a code.  This form is meant to  be used together with the
function <C>BoundsMinimumDistance</C> 
(see <Ref Func="BoundsMinimumDistance" Style="Number"/>), if the
bounds are already calculated.
</Description>
</ManSection>

<Example>
gap> C1 := BestKnownLinearCode( 23, 12, GF(2) );
a linear [23,12,7]3 punctured code
gap> C1 = BinaryGolayCode();
false     # it's constructed differently
gap> C1 := BestKnownLinearCode( 23, 12, GF(2) );
a linear [23,12,7]3 punctured code
gap> G1 := MutableCopyMat(GeneratorMat(C1));;
gap> PutStandardForm(G1);
()
gap> Display(G1);
 1 . . . . . . . . . . . 1 . 1 . 1 1 1 . . . 1
 . 1 . . . . . . . . . . 1 1 1 1 1 . . 1 . . .
 . . 1 . . . . . . . . . 1 1 . 1 . . 1 . 1 . 1
 . . . 1 . . . . . . . . 1 1 . . . 1 1 1 . 1 .
 . . . . 1 . . . . . . . 1 1 . . 1 1 . 1 1 . 1
 . . . . . 1 . . . . . . . 1 1 . . 1 1 . 1 1 1
 . . . . . . 1 . . . . . . . 1 1 . . 1 1 . 1 1
 . . . . . . . 1 . . . . 1 . 1 1 . 1 1 1 1 . .
 . . . . . . . . 1 . . . . 1 . 1 1 . 1 1 1 1 .
 . . . . . . . . . 1 . . . . 1 . 1 1 . 1 1 1 .
 . . . . . . . . . . 1 . 1 . 1 1 1 . . . 1 1 1
 . . . . . . . . . . . 1 . 1 . 1 1 1 . . . 1 1
gap> C2 := BinaryGolayCode();
a cyclic [23,12,7]3 binary Golay code over GF(2)
gap> G2 := MutableCopyMat(GeneratorMat(C2));;
gap> PutStandardForm(G2);
()
gap> Display(G2);
 1 . . . . . . . . . . . 1 . 1 . 1 1 1 . . . 1
 . 1 . . . . . . . . . . 1 1 1 1 1 . . 1 . . 1
 . . 1 . . . . . . . . . 1 1 . 1 . . 1 . 1 . 1
 . . . 1 . . . . . . . . 1 1 . . . 1 1 1 . 1 1
 . . . . 1 . . . . . . . 1 1 . . 1 1 . 1 1 . .
 . . . . . 1 . . . . . . . 1 1 . . 1 1 . 1 1 .
 . . . . . . 1 . . . . . . . 1 1 . . 1 1 . 1 1
 . . . . . . . 1 . . . . 1 . 1 1 . 1 1 1 1 . .
 . . . . . . . . 1 . . . . 1 . 1 1 . 1 1 1 1 .
 . . . . . . . . . 1 . . . . 1 . 1 1 . 1 1 1 1
 . . . . . . . . . . 1 . 1 . 1 1 1 . . . 1 1 .
 . . . . . . . . . . . 1 . 1 . 1 1 1 . . . 1 1
## Despite their generator matrices are different, they are equivalent codes, see below.
gap> IsEquivalent(C1,C2);
true
gap> CodeIsomorphism(C1,C2);
(4,14,6,12,5)(7,17,18,11,19)(8,22,13,21,16)(10,23,15,20)
gap> Display( BestKnownLinearCode( 81, 77, GF(4) ) );
a linear [81,77,3]2..3 shortened code of
a linear [85,81,3]1 Hamming (4,4) code over GF(4)
gap> C:=BestKnownLinearCode(174,72);
a linear [174,72,31..36]26..87 code defined by generator matrix over GF(2)
gap> bounds := BoundsMinimumDistance( 81, 77, GF(4) );
rec( n := 81, k := 77, q := 4, 
  references := rec( Ham := [ "%T this reference is unknown, for more info", 
          "%T contact A.E. Brouwer (aeb@cwi.nl)" ], 
      cap := [ "%T this reference is unknown, for more info", 
          "%T contact A.E. Brouwer (aeb@cwi.nl)" ] ), 
  construction := [ (Operation "ShortenedCode"), 
      [ [ (Operation "HammingCode"), [ 4, 4 ] ], [ 1, 2, 3, 4 ] ] ], 
  lowerBound := 3, 
  lowerBoundExplanation := [ "Lb(81,77)=3, by shortening of:", 
      "Lb(85,81)=3, reference: Ham" ], upperBound := 3, 
  upperBoundExplanation := [ "Ub(81,77)=3, by considering shortening to:", 
      "Ub(18,14)=3, reference: cap" ] )
gap> C := BestKnownLinearCode( bounds );
a linear [81,77,3]2..3 shortened code
gap> C = BestKnownLinearCode(81, 77, GF(4) );
true
</Example>

<!--
C1 := BestKnownLinearCode( 23, 12, GF(2) );
C1 = BinaryGolayCode();
C1 := BestKnownLinearCode( 23, 12, GF(2) );
G1 := MutableCopyMat(GeneratorMat(C1));;
PutStandardForm(G1);
Display(G1);
C2 := BinaryGolayCode();
G2 := MutableCopyMat(GeneratorMat(C2));;
PutStandardForm(G2);
Display(G2);
IsEquivalent(C1,C2);
CodeIsomorphism(C1,C2);
Display( BestKnownLinearCode( 81, 77, GF(4) ) );
C:=BestKnownLinearCode(174,72);
bounds := BoundsMinimumDistance( 81, 77, GF(4) );
C := BestKnownLinearCode( bounds );
C = BestKnownLinearCode(81, 77, GF(4) );
-->

</Section>


<Section>
<Heading>
Gabidulin Codes
</Heading>
<Label Name="Gabidulin Codes"/>

<!--
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%Section   GabidulinCode, EnlargedGabidulinCode, DavydovCode,
%          TombakCode, EnlargedTombakCode
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-->


These five binary, linear 
codes are derived from an article by Gabidulin, Davydov and
Tombak <Cite Key="GDT91"/>. All these codes are defined by 
check matrices.
Exact definitions can be found in the article.
The Gabidulin code, the enlarged Gabidulin code, the Davydov code, the
Tombak code, and the enlarged Tombak code, correspond with theorem 1,  2,
3, 4, and 5, respectively in the article.
<P/>
Like the Hamming codes, these codes have fixed minimum 
distance and covering radius, but can be arbitrarily long. 


<Index>
code, Gabidulin
</Index>

<ManSection>
<Func Name="GabidulinCode" Arg=" m w1 w2 "/>

<Description>
<C>GabidulinCode</C> yields a code of length <M>5</M> . 
<M>2^{m-2}-1</M>, redundancy <M>2m-1</M>, 
minimum distance <M>3</M> and covering radius <M>2</M>.
<A>w1</A> and <A>w2</A> should be elements of 
<M>GF(2^{m-2})</M>.
</Description>
</ManSection>

<ManSection>
<Func Name="EnlargedGabidulinCode" Arg=" m w1 w2 e "/>

<Description>
<C>EnlargedGabidulinCode</C> yields a code of length 
<M>7</M>. <M>2^{m-2}-2</M>, redundancy <M>2m</M>, 
minimum distance <M>3</M> and covering radius <M>2</M>.
<A>w1</A> and <A>w2</A> are elements of 
<M>GF(2^{m-2})</M>. <A>e</A> is an element of 
<M>GF(2^m)</M>.
<!--
The core of an enlarged Gabidulin code consists of a Gabidulin code.
-->
</Description>
</ManSection>

<Index>
code, Davydov
</Index>

<ManSection>
<Func Name="DavydovCode" Arg=" r v ei ej "/>

<Description>
<C>DavydovCode</C> yields a code of length <M>2^v + 2^{r-v} - 3</M>,
redundancy <A>r</A>, minimum distance <M>4</M> 
and covering radius <M>2</M>. <A>v</A> is an integer between 
<M>2</M> and <M>r-2</M>. <A>ei</A> and <A>ej</A> are 
elements of <M>GF(2^v)</M> and <M>GF(2^{r-v})</M>,
respectively.
</Description>
</ManSection>

<Index>
code, Tombak
</Index>

<ManSection>
<Func Name="TombakCode" Arg=" m e beta gamma w1 w2 "/>

<Description>
<C>TombakCode</C> yields a code of length 
<M>15 \cdot 2^{m-3} - 3</M>,
redundancy <M>2m</M>, minimum distance <M>4</M> and 
covering radius <M>2</M>.
<A>e</A> is an element of <M>GF(2^m)</M>.
<A>beta</A> and <A>gamma</A> are elements of 
<M>GF(2^{m-1})</M>.
<A>w1</A> and <A>w2</A> are elements of 
<M>GF(2^{m-3})</M>.
</Description>
</ManSection>

<ManSection>
<Func Name="EnlargedTombakCode" Arg=" m e beta gamma w1 w2 u "/>

<Description>
<C>EnlargedTombakCode</C> yields a code of length 
<M>23 \cdot 2^{m-4} - 3</M>, redundancy <M>2m-1</M>, 
minimum distance <M>4</M> and covering radius <M>2</M>.
The parameters <A>m</A>, <A>e</A>, <A>beta</A>, <A>gamma</A>, 
<A>w1</A> and <A>w2</A> are defined as in <C>TombakCode</C>.
<A>u</A> is an element of <M>GF(2^{m-1})</M>.
<!--
The core of an enlarged Tombak code consists of a Tombak code.
-->
</Description>
</ManSection>

<Example>
gap> GabidulinCode( 4, Z(4)^0, Z(4)^1 );
a linear [19,12,3]2 Gabidulin code (m=4) over GF(2)
gap> EnlargedGabidulinCode( 4, Z(4)^0, Z(4)^1, Z(16)^11 );
a linear [26,18,3]2 enlarged Gabidulin code (m=4) over GF(2)
gap> DavydovCode( 6, 3, Z(8)^1, Z(8)^5 );
a linear [13,7,4]2 Davydov code (r=6, v=3) over GF(2)
gap> TombakCode( 5, Z(32)^6, Z(16)^14, Z(16)^10, Z(4)^0, Z(4)^1 );
a linear [57,47,4]2 Tombak code (m=5) over GF(2)
gap> EnlargedTombakCode( 6, Z(32)^6, Z(16)^14, Z(16)^10,
> Z(4)^0, Z(4)^0, Z(32)^23 );
a linear [89,78,4]2 enlarged Tombak code (m=6) over GF(2)
</Example>
<!--
GabidulinCode( 4, Z(4)^0, Z(4)^1 );
EnlargedGabidulinCode( 4, Z(4)^0, Z(4)^1, Z(16)^11 );
DavydovCode( 6, 3, Z(8)^1, Z(8)^5 );
TombakCode( 5, Z(32)^6, Z(16)^14, Z(16)^10, Z(4)^0, Z(4)^1 );
EnlargedTombakCode( 6, Z(32)^6, Z(16)^14, Z(16)^10, Z(4)^0, Z(4)^0, Z(32)^23 );
-->

</Section>

<Section>
<Heading>
Golay Codes
</Heading>
<Label Name="Golay Codes"/>

<Q>
The Golay code is probably the most important of all codes 
for both practical and theoretical reasons. 
</Q>
(<Cite Key="MS83"/>, pg. 64).
Though born in Switzerland, M. J. E. Golay (1902-1989) worked for 
the US Army Labs for most of his career.
For more information on his life, see his obit in the June 
1990 IEEE Information Society Newsletter.

<Index>
code, Golay (binary)
</Index>

<ManSection>
<Func Name="BinaryGolayCode" Arg="  "/>

<Description>
<C>BinaryGolayCode</C> returns a binary Golay code. This is a perfect
<M>[23,12,7]</M>  code. It is also cyclic, and has generator polynomial
<M>g(x)=1+x^2+x^4+x^5+x^6+x^{10}+x^{11}</M>.  
Extending it results in an extended Golay code (see  
<Ref Func="ExtendedBinaryGolayCode" Style="Number"/>).  There's  also  the
ternary Golay code (see 
<Ref Func="TernaryGolayCode" Style="Number"/>).
</Description>
</ManSection>

<Example>
gap> C:=BinaryGolayCode();
a cyclic [23,12,7]3 binary Golay code over GF(2)
gap> ExtendedBinaryGolayCode() = ExtendedCode(BinaryGolayCode());
true
gap> IsPerfectCode(C);
true 
gap> IsCyclicCode(C);
true
</Example>
<!--
C:=BinaryGolayCode();
ExtendedBinaryGolayCode() = ExtendedCode(BinaryGolayCode());
IsPerfectCode(C);
IsCyclicCode(C);
-->

<ManSection>
<Func Name="ExtendedBinaryGolayCode" Arg="  "/>

<Description>
<C>ExtendedBinaryGolayCode</C> returns an extended binary Golay code. 
This is a <M>[24,12,8]</M> code. Puncturing in the last position 
results in a perfect binary Golay code 
(see <Ref Func="BinaryGolayCode" Style="Number"/>). 
The code is self-dual.
</Description>
</ManSection>

<Example>
gap> C := ExtendedBinaryGolayCode();
a linear [24,12,8]4 extended binary Golay code over GF(2)
gap> IsSelfDualCode(C);
true
gap> P := PuncturedCode(C);
a linear [23,12,7]3 punctured code
gap> P = BinaryGolayCode();
true 
gap> IsCyclicCode(C);
false

</Example>
<!--
C := ExtendedBinaryGolayCode();
IsSelfDualCode(C);
P := PuncturedCode(C);
P = BinaryGolayCode();
IsCyclicCode(C);
-->

<Index>
code, Golay (ternary)
</Index>

<ManSection>
<Func Name="TernaryGolayCode" Arg="  "/>

<Description>
<C>TernaryGolayCode</C> returns a ternary Golay code.
This is a perfect <M>[11,6,5]</M> code. 
It is also cyclic, and  has generator polynomial
<M>g(x)=2+x^2+2x^3+x^4+x^5</M>. 
Extending it results in an extended Golay code
(see <Ref Func="ExtendedTernaryGolayCode" Style="Number"/>). 
There's also the binary Golay code (see
<Ref Func="BinaryGolayCode" Style="Number"/>).
</Description>
</ManSection>

<Example>
gap> C:=TernaryGolayCode();
a cyclic [11,6,5]2 ternary Golay code over GF(3)
gap> ExtendedTernaryGolayCode() = ExtendedCode(TernaryGolayCode());
true 
gap> IsCyclicCode(C);
true
</Example>
<!--
C:=TernaryGolayCode();
ExtendedTernaryGolayCode() = ExtendedCode(TernaryGolayCode());
IsCyclicCode(C);
-->

<ManSection>
<Func Name="ExtendedTernaryGolayCode" Arg="  "/>

<Description>
<C>ExtendedTernaryGolayCode</C> returns an 
extended ternary Golay code. 
This is a <M>[12,6,6]</M> code. Puncturing this code 
results in a perfect ternary Golay code 
(see <Ref Func="TernaryGolayCode" Style="Number"/>). 
The code is self-dual.
</Description>
</ManSection>

<Example>
gap> C := ExtendedTernaryGolayCode();
a linear [12,6,6]3 extended ternary Golay code over GF(3)
gap> IsSelfDualCode(C);
true
gap> P := PuncturedCode(C);
a linear [11,6,5]2 punctured code
gap> P = TernaryGolayCode();
true 
gap> IsCyclicCode(C);
false
</Example>
<!--
C := ExtendedTernaryGolayCode();
IsSelfDualCode(C);
P := PuncturedCode(C);
P = TernaryGolayCode();
IsCyclicCode(C);
-->

</Section>

<Section>
<Heading>
Generating Cyclic Codes
</Heading>
<Label Name="Generating Cyclic Codes"/>


The  elements of a cyclic code <M>C</M> are all 
multiples of a ('generator') polynomial <M>g(x)</M>, 
where calculations are carried out modulo <M>x^n-1</M>. 
Therefore, as polynomials in <M>x</M>, the elements always 
have degree less than <M>n</M>. A cyclic code is an ideal in
the ring <M>F[x]/(x^n-1)</M> of polynomials modulo 
<M>x^n - 1</M>. The unique monic polynomial 
of least degree that generates <M>C</M>
is called the <E>generator polynomial</E> of <M>C</M>.
It is a divisor of the polynomial <M>x^n-1</M>.
<Index>generator polynomial</Index>
<Index>check polynomial</Index>
<P/>

The <E>check polynomial</E> is the polynomial <M>h(x)</M> with 
<M>g(x)h(x)=x^n-1</M>. Therefore it is also a divisor of 
<M>x^n-1</M>. The check polynomial has the property that
<Display>
c(x)h(x) \equiv  0 \pmod{x^n-1},
</Display>
for every codeword <M>c(x)\in C</M>.
<P/>
The first two functions described below 
generate cyclic codes from a given generator or check 
polynomial. All cyclic codes can be constructed using
these functions.
<P/>
Two of the Golay codes already described are cyclic 
(see <Ref Func="BinaryGolayCode" Style="Number"/>  and
<Ref Func="TernaryGolayCode" Style="Number"/>). For example,
the <Package>GUAVA</Package> record for a binary
Golay code contains the generator polynomial:

<Example>
gap> C := BinaryGolayCode();
a cyclic [23,12,7]3 binary Golay code over GF(2)
gap> NamesOfComponents(C);
[ "LeftActingDomain", "GeneratorsOfLeftOperatorAdditiveGroup", "WordLength",
  "GeneratorMat", "GeneratorPol", "Dimension", "Redundancy", "Size", "name",
  "lowerBoundMinimumDistance", "upperBoundMinimumDistance", "WeightDistribution",
  "boundsCoveringRadius", "MinimumWeightOfGenerators", 
  "UpperBoundOptimalMinimumDistance" ]
gap> C!.GeneratorPol;
x_1^11+x_1^10+x_1^6+x_1^5+x_1^4+x_1^2+Z(2)^0
</Example>
<!--
C := BinaryGolayCode();
NamesOfComponents(C);
C!.GeneratorPol;
-->

Then functions that generate cyclic codes from a prescribed set of roots
of the generator polynomial are described, including the BCH codes (see
<Ref Func="RootsCode" Style="Number"/>, 
<Ref Func="BCHCode" Style="Number"/>, 
<Ref Func="ReedSolomonCode" Style="Number"/> and 
<Ref Func="QRCode" Style="Number"/>).
<P/>
Finally we describe the trivial codes 
(see <Ref Func="WholeSpaceCode" Style="Number"/>,  
<Ref Func="NullCode" Style="Number"/>,
<Ref Func="RepetitionCode" Style="Number"/>), and
the command <C>CyclicCodes</C> which lists all   
cyclic codes (<Ref Func="CyclicCodes" Style="Number"/>).

<ManSection>
<Func Name="GeneratorPolCode" Arg=" g n [name] F "/>

<Description>
<C>GeneratorPolCode</C> creates a cyclic code with a 
generator polynomial <A>g</A>, word length <A>n</A>, 
over <A>F</A>.  <A>name</A> can contain  a short
description of the code.
<P/>
If <A>g</A> is not a divisor of <M>x^n-1</M>, it cannot be 
a generator polynomial. In that case,  a code is created 
with generator polynomial <M>gcd( g,  x^n-1 )</M>, 
i.e. the greatest common divisor of <A>g</A> and
<M>x^n-1</M>. This is a valid generator polynomial 
that generates the ideal <M>(g)</M>. 
See <Ref Func="Generating Cyclic Codes" Style="Number"/>.
</Description>
</ManSection>

<Example>
gap> x:= Indeterminate( GF(2) );; P:= x^2+1;
Z(2)^0+x^2
gap> C1 := GeneratorPolCode(P, 7, GF(2));
a cyclic [7,6,1..2]1 code defined by generator polynomial over GF(2)
gap> GeneratorPol( C1 );
Z(2)^0+x
gap> C2 := GeneratorPolCode( x+1, 7, GF(2)); 
a cyclic [7,6,1..2]1 code defined by generator polynomial over GF(2)
gap> GeneratorPol( C2 );
Z(2)^0+x
</Example>
<!--
x:= Indeterminate( GF(2) );; P:= x^2+1;
C1 := GeneratorPolCode(P, 7, GF(2));
GeneratorPol( C1 );
C2 := GeneratorPolCode( x+1, 7, GF(2)); 
GeneratorPol( C2 );
-->

<ManSection>
<Func Name="CheckPolCode" Arg=" h n [name] F "/>

<Description>
<C>CheckPolCode</C> creates a cyclic code with a check polynomial 
<A>h</A>, word length <A>n</A>, over <A>F</A>. <A>name</A> 
can contain a short description of the code (as a string).
<P/>
If <A>h</A> is not a divisor of <M>x^n-1</M>, it cannot be a 
check polynomial. In that case, a code is created with check 
polynomial <M>gcd( h, x^n-1 )</M>,
i.e. the greatest common divisor of <A>h</A> and 
<M>x^n-1</M>. This is a valid check polynomial that yields 
the same elements as the ideal <M>(h)</M>. See
<Ref Label="Generating Cyclic Codes" Style="Number"/>.

</Description>
</ManSection>

<Example>
gap>  x:= Indeterminate( GF(3) );; P:= x^2+2;
-Z(3)^0+x_1^2
gap> H := CheckPolCode(P, 7, GF(3));
a cyclic [7,1,7]4 code defined by check polynomial over GF(3)
gap> CheckPol(H);
-Z(3)^0+x_1
gap> Gcd(P, X(GF(3))^7-1);
-Z(3)^0+x_1
</Example>
<!--
x:= Indeterminate( GF(3) );; P:= x^2+2;
H := CheckPolCode(P, 7, GF(3));
CheckPol(H);
Gcd(P, X(GF(3))^7-1);
-->


<ManSection>
<Func Name="RootsCode" Arg=" n list "/>

<Description>
This is the generalization of the BCH, Reed-Solomon and quadratic residue
codes (see 
<Ref Func="BCHCode" Style="Number"/>, 
<Ref Func="ReedSolomonCode" Style="Number"/> and  
<Ref Func="QRCode" Style="Number"/>). The user can give
a length of  the code <A>n</A> and a prescribed set of zeros. The argument
<A>list</A> must be a valid  list of <M>n^{th}</M> 
roots of unity in a splitting field <M>GF(q^m)</M>.  
The resulting  code  will be over  the  field
<M>GF(q)</M>. The function will return the largest possible cyclic code for
which  the list <A>list</A> is  a subset of the roots of the code. From this
list, <Package>GUAVA</Package> calculates the entire set of roots.
<P/>
This command can also be called with the syntax
<C>RootsCode( n, list, q )</C>.
In this second form,  the second argument is a  list of integers, ranging
from <M>0</M> to <M>n-1</M>. 
The resulting code will be over a field <M>GF(q)</M>. 
<Package>GUAVA</Package>
calculates a primitive <M>n^{th}</M> root of unity, <M>\alpha</M>, in the
extension field of <M>GF(q)</M>. It uses the set of the powers of 
<M>\alpha</M> in the list as a prescribed set of zeros.
</Description>
</ManSection>

<Example>
gap> a := PrimitiveUnityRoot( 3, 14 );
Z(3^6)^52
gap> C1 := RootsCode( 14, [ a^0, a, a^3 ] );
a cyclic [14,7,3..6]3..7 code defined by roots over GF(3)
gap> MinimumDistance( C1 );
4
gap> b := PrimitiveUnityRoot( 2, 15 );
Z(2^4)
gap> C2 := RootsCode( 15, [ b, b^2, b^3, b^4 ] );
a cyclic [15,7,5]3..5 code defined by roots over GF(2)
gap> C2 = BCHCode( 15, 5, GF(2) );
true 
gap> C3 := RootsCode( 4, [ 1, 2 ], 5 );
a cyclic [4,2,2..3]2 code defined by roots over GF(5)
gap> RootsOfCode( C3 );
[ Z(5), Z(5)^2 ]
gap> C3 = ReedSolomonCode( 4, 3 );
true
</Example>
<!--
a := PrimitiveUnityRoot( 3, 14 );
C1 := RootsCode( 14, [ a^0, a, a^3 ] );
MinimumDistance( C1 );
b := PrimitiveUnityRoot( 2, 15 );
C2 := RootsCode( 15, [ b, b^2, b^3, b^4 ] );
C2 = BCHCode( 15, 5, GF(2) );
C3 := RootsCode( 4, [ 1, 2 ], 5 );
RootsOfCode( C3 );
C3 = ReedSolomonCode( 4, 3 );
-->

<Index>
code, Bose-Chaudhuri-Hockenghem
</Index>


<ManSection>
<Func Name="BCHCode" Arg=" n [b] delta F "/>

<Description>
The function <C>BCHCode</C> returns a 
'Bose-Chaudhuri-Hockenghem code' (or <E>BCH code</E> for short). 
This is the largest possible cyclic code of length <A>n</A>
over field <A>F</A>, whose generator polynomial has zeros 
<Display>
a^{b},a^{b+1}, ..., a^{b+delta-2}, 
</Display>
where <M>a</M> is a primitive <M>n^{th}</M> root of unity in
the splitting field <M>GF(q^m)</M>, <A>b</A> is an integer 
<M>0\leq b\leq n-delta+1</M> and <M>m</M> is the
multiplicative order of <M>q</M> modulo <A>n</A>.  
(The integers <M>\{b,...,b+delta-2\}</M>
typically lie in the range <M>\{1,...,n-1\}</M>.)
Default  value  for <A>b</A> is <M>1</M>, though the algorithm
allows <M>b=0</M>. The length <A>n</A> of the code and the size <M>q</M> of 
the field must be relatively prime. 
The generator polynomial is equal to the least common multiple of the
minimal polynomials of 
<Display>
a^{b}, a^{b+1}, ..., a^{b+delta-2}.
</Display>
The set of zeroes of the generator polynomial is equal to the
union of the sets 
<Display>
\{a^x\ |\ x \in C_k\},
</Display>
where <M>C_k</M> is the <M>k^{th}</M> cyclotomic coset of 
<M>q</M> modulo <M>n</M>
and <M>b\leq k\leq b+delta-2</M> (see 
<Ref Func="CyclotomicCosets" Style="Number"/>).
<P/>
Special cases are <M>b=1</M> (resulting codes are called 'narrow-sense' 
BCH codes), and <M>n=q^m-1</M> (known as 'primitive' BCH codes). 
<Package>GUAVA</Package>
calculates the largest value of <M>d</M> for which the BCH code with
designed distance <M>d</M> coincides with the BCH code with designed
distance <A>delta</A>. This distance <M>d</M> is called the 
<E>Bose distance</E> of the code.
The true minimum distance of the code is greater than or equal to the
Bose distance.
<Index>Bose distance</Index>
<P/>
Printed are the designed distance (to be precise, the Bose distance)
<M>d</M>, and the starting power <M>b</M>.
<P/>
The Sugiyama decoding algorithm has been implemented for this code
(see <Ref Func="Decode" Style="Number"/>).
</Description>
</ManSection>

<Example>
gap> C1 := BCHCode( 15, 3, 5, GF(2) );
a cyclic [15,5,7]5 BCH code, delta=7, b=1 over GF(2)
gap> DesignedDistance( C1 );
7
gap> C2 := BCHCode( 23, 2, GF(2) );
a cyclic [23,12,5..7]3 BCH code, delta=5, b=1 over GF(2)
gap> DesignedDistance( C2 );       
5
gap> MinimumDistance(C2);
7 
</Example>
<!--
C1 := BCHCode( 15, 3, 5, GF(2) );
DesignedDistance( C1 );
C2 := BCHCode( 23, 2, GF(2) );
DesignedDistance( C2 );       
MinimumDistance(C2);
-->

See <Ref Func="RootsCode" Style="Number"/>
for a more general construction.

<Index>
code, Reed-Solomon
</Index>

<ManSection>
<Func Name="ReedSolomonCode" Arg=" n d "/>

<Description>
<C>ReedSolomonCode</C> returns a  'Reed-Solomon code' of length  
<A>n</A>, designed distance <A>d</A>. 
This code is a primitive narrow-sense BCH  code over the
field <M>GF(q)</M>,  where <M>q=n+1</M>.  
The dimension of an RS code is <M>n-d+1</M>. 
According to the Singleton bound 
(see <Ref Func="UpperBoundSingleton" Style="Number"/>)
the dimension cannot be greater than this, so the true minimum distance
of an RS code is equal to <A>d</A> and the code is maximum distance separable
(see <Ref Func="IsMDSCode" Style="Number"/>).
</Description>
</ManSection>

<Example>
gap> C1 := ReedSolomonCode( 3, 2 );
a cyclic [3,2,2]1 Reed-Solomon code over GF(4)
gap> IsCyclicCode(C1);
true
gap> C2 := ReedSolomonCode( 4, 3 );
a cyclic [4,2,3]2 Reed-Solomon code over GF(5)
gap> RootsOfCode( C2 );
[ Z(5), Z(5)^2 ]
gap> IsMDSCode(C2);
true 
</Example>
<!--
C1 := ReedSolomonCode( 3, 2 );
IsCyclicCode(C1);
C2 := ReedSolomonCode( 4, 3 );
RootsOfCode( C2 );
IsMDSCode(C2);
-->

See <Ref Func="GeneralizedReedSolomonCode" Style="Number"/>
for a more general construction.

<ManSection>
	<Func Name="ExtendedReedSolomonCode" Arg=" n d "/>
	<Description>
		<C>ExtendedReedSolomonCode</C> creates a Reed-Solomon
		code of length <M>n-1</M> with designed distance <M>d-1</M>
		and then returns the code which is extended by adding an
		overall parity-check symbol. The motivation for creating this
		function is calling <Ref Func="ExtendedCode" Style="Number"/>
		function over a Reed-Solomon code will take considerably long
		time.
	</Description>
</ManSection>

<Example>
gap> C := ExtendedReedSolomonCode(17, 13);
a linear [17,5,13]9..12 extended Reed Solomon code over GF(17)
gap> IsMDSCode(C);
true
</Example>
<!--
C := ExtendedReedSolomonCode(17, 13);
IsMDSCode(C);
-->

<ManSection>
<Func Name="QRCode" Arg=" n F "/>

<Description>
<C>QRCode</C> returns a quadratic residue code. If <A>F</A> 
is a field <M>GF(q)</M>, then <M>q</M> must be a quadratic residue 
modulo <A>n</A>. That is, an <M>x</M> exists with 
<M>x^2 \equiv q  \pmod n</M>. Both <A>n</A> and <M>q</M> must  
be primes.  Its generator polynomial is the product of the 
polynomials <M>x-a^i</M>. <M>a</M> is a primitive <M>n^{th}</M> 
root of unity, and <M>i</M> is an integer in the set of
quadratic residues modulo <A>n</A>.
</Description>
</ManSection>

<Example>
gap> C1 := QRCode( 7, GF(2) );
a cyclic [7,4,3]1 quadratic residue code over GF(2)
gap> IsEquivalent( C1, HammingCode( 3, GF(2) ) );
true
gap> IsCyclicCode(C1);
true
gap> IsCyclicCode(HammingCode( 3, GF(2) ));
false
gap> C2 := QRCode( 11, GF(3) );
a cyclic [11,6,4..5]2 quadratic residue code over GF(3)
gap> C2 = TernaryGolayCode();
true 
gap> Q1 := QRCode( 7, GF(2));
a cyclic [7,4,3]1 quadratic residue code over GF(2)
gap> P1:=AutomorphismGroup(Q1); IdGroup(P1);
Group([ (1,2)(5,7), (2,3)(4,7), (2,4)(5,6), (3,5)(6,7), (3,7)(5,6) ])
[ 168, 42 ]
</Example>
<!--
C1 := QRCode( 7, GF(2) );
IsEquivalent( C1, HammingCode( 3, GF(2) ) );
C2 := QRCode( 11, GF(3) );
C2 = TernaryGolayCode();
Q1 := QRCode( 7, GF(2));
P1:=AutomorphismGroup(Q1); 
IdGroup(P1);

-->

<ManSection>
<Func Name="QQRCodeNC" Arg=" p "/>

<Description>
<C>QQRCodeNC</C> is the same as <C>QQRCode</C>, except that
it uses <C>GeneratorMatCodeNC</C> instead of
<C>GeneratorMatCode</C>.

</Description>
</ManSection>

<ManSection>
<Func Name="QQRCode" Arg=" p "/>

<Description>
<C>QQRCode</C> returns a quasi-quadratic residue code, as defined by
Proposition 2.2 in Bazzi-Mittel <Cite Key="BM03"/>. The
parameter <A>p</A> must be a prime.
Its generator matrix has the block form <M>G=(Q,N)</M>.
Here <M>Q</M> is a <M>p\times </M> circulant matrix
whose top row is <M>(0,x_1,...,x_{p-1})</M>, where
<M>x_i=1</M> if and only if <M>i</M> is a quadratic residue mod <M>p</M>,
and <M>N</M> is a <M>p\times </M> circulant matrix
whose top row is <M>(0,y_1,...,y_{p-1})</M>, where
<M>x_i+y_i=1</M> for all <M>i</M>. (In fact, this matrix
can be recovered as the component <C>DoublyCirculant</C>
of the code.)

</Description>
</ManSection>

<Example>
gap> C1 := QQRCode( 7);
a linear [14,7,1..4]3..5 code defined by generator matrix over GF(2)
gap> G1:=GeneratorMat(C1);;
gap> Display(G1);
 . 1 1 . 1 . . . . . 1 . 1 1
 1 . 1 1 1 . . . . 1 1 1 . 1
 . . . 1 1 . 1 . 1 1 . . . 1
 . . 1 . 1 1 1 1 . 1 . . 1 1
 . . . . . . . 1 . . 1 1 1 .
 . . . . . . . . . 1 1 1 . 1
 . . . . . . . . 1 . . 1 1 1
gap> Display(C1!.DoublyCirculant);
 . 1 1 . 1 . . . . . 1 . 1 1
 1 1 . 1 . . . . . 1 . 1 1 .
 1 . 1 . . . 1 . 1 . 1 1 . .
 . 1 . . . 1 1 1 . 1 1 . . .
 1 . . . 1 1 . . 1 1 . . . 1
 . . . 1 1 . 1 1 1 . . . 1 .
 . . 1 1 . 1 . 1 . . . 1 . 1
gap> MinimumDistance(C1);
4
gap> C2 := QQRCode( 29); MinimumDistance(C2);
a linear [58,28,1..14]8..29 code defined by generator matrix over GF(2)
12
gap> Aut2:=AutomorphismGroup(C2); IdGroup(Aut2);
[ permutation group of size 812 with 4 generators ]
[ 812, 7 ]
</Example>

<!--
C1 := QQRCode( 7);
G1:=GeneratorMat(C1);;
Display(G1);
Display(C1!.DoublyCirculant);
MinimumDistance(C1);
C2 := QQRCode( 29); MinimumDistance(C2);
Aut2:=AutomorphismGroup(C2); IdGroup(Aut2);
-->

<Index>
code, Fire
</Index>


<ManSection>
<Func Name="FireCode" Arg=" g b "/>

<Description>
<C>FireCode</C> constructs a (binary) Fire code. 
<A>g</A> is a primitive polynomial of degree <M>m</M>, 
and a factor of <M>x^r-1</M>. <A>b</A> an integer 
<M>0 \leq  b \leq m</M> 
not divisible by <M>r</M>,  that determines the burst length  
of a single error burst that can be corrected. 
The argument <A>g</A> can be a polynomial with base ring 
<M>GF(2)</M>, or a list of coefficients in <M>GF(2)</M>.  
The generator polynomial of the code is defined as the product of 
<A>g</A> and <M>x^{2b-1}+1</M>.
<P/>
Here is the general definition of 'Fire code', named after
P. Fire, who introduced these codes in 1959 in order to
correct burst errors. 
First, a definition. If <M>F=GF(q)</M> and
<M>f\in F[x]</M> then we say <M>f</M> has
<E>order</E> <M>e</M> if <M>f(x)|(x^e-1)</M>.
<Index>order of polynomial</Index>
A <E>Fire code</E> is a cyclic code over <M>F</M>
with generator polynomial <M>g(x)=
(x^{2t-1}-1)p(x)</M>, where <M>p(x)</M>
does not divide <M>x^{2t-1}-1</M> and satisfies 
<M>deg(p(x))\geq t</M>. The length of such a code
is the order of <M>g(x)</M>.
<!-- 
If <M>p(x)</M> is an irreducible polynomial
in <M>F[x]</M> of degree <M>m</M>
and order <M>e</M> then the order of <M>g(x)</M>
is equal to <M>lcm(e,2t-1)</M>.
-->
Non-binary Fire codes have not been implemented.
</Description>
</ManSection>
.

<Example>
gap> x:= Indeterminate( GF(2) );; G:= x^3+x^2+1;
Z(2)^0+x^2+x^3
gap> Factors( G );
[ Z(2)^0+x^2+x^3 ]
gap> C := FireCode( G, 3 );
a cyclic [35,27,1..4]2..6 3 burst error correcting fire code over GF(2)
gap> MinimumDistance( C );
4     # Still it can correct bursts of length 3 
</Example>
<!--
x:= Indeterminate( GF(2) );; G:= x^3+x^2+1;
Factors( G );
C := FireCode( G, 3 );
MinimumDistance( C );
-->


<ManSection>
<Func Name="WholeSpaceCode" Arg=" n F "/>

<Description>
<C>WholeSpaceCode</C> returns the cyclic whole space code of 
length <A>n</A> over <A>F</A>. This code consists of all polynomials 
of degree less than <A>n</A> and coefficients in <A>F</A>.
</Description>
</ManSection>

<Example>
gap> C := WholeSpaceCode( 5, GF(3) );
a cyclic [5,5,1]0 whole space code over GF(3)
</Example>
<!--
C := WholeSpaceCode( 5, GF(3) );
-->



<ManSection>
<Func Name="NullCode" Arg=" n F "/>

<Description>
<C>NullCode</C> returns the zero-dimensional nullcode with length  
<A>n</A> over <A>F</A>. This code has only one word: the all zero word. 
It is cyclic though!
</Description>
</ManSection>

<Example>
gap> C := NullCode( 5, GF(3) );
a cyclic [5,0,5]5 nullcode over GF(3)
gap> AsSSortedList( C );
[ [ 0 0 0 0 0 ] ]
</Example>
<!--

-->


<ManSection>
<Func Name="RepetitionCode" Arg=" n F "/>

<Description>
<C>RepetitionCode</C> returns the cyclic repetition code of 
length <A>n</A> over <A>F</A>. The code has as many elements as 
<A>F</A>, because each codeword consists of a repetition of one of 
these elements.
</Description>
</ManSection>

<Example>
gap> C := RepetitionCode( 3, GF(5) );
a cyclic [3,1,3]2 repetition code over GF(5)
gap> AsSSortedList( C );
[ [ 0 0 0 ], [ 1 1 1 ], [ 2 2 2 ], [ 4 4 4 ], [ 3 3 3 ] ]
gap> IsPerfectCode( C );
false
gap> IsMDSCode( C );
true 
</Example>
<!--
C := RepetitionCode( 3, GF(5) );
AsSSortedList( C );
IsPerfectCode( C );
IsMDSCode( C );
-->

<ManSection>
<Func Name="CyclicCodes" Arg=" n F "/>

<Description>
<C>CyclicCodes</C> returns a list of all cyclic codes of length <A>n</A> 
over <A>F</A>. It constructs all possible generator polynomials 
from the factors of <M>x^n-1</M>. Each combination of these 
factors yields a generator polynomial after multiplication.
</Description>
</ManSection>

<Example>
gap> CyclicCodes(3,GF(3));
[ a cyclic [3,3,1]0 enumerated code over GF(3), 
a cyclic [3,2,1..2]1 enumerated code over GF(3), 
a cyclic [3,1,3]2 enumerated code over GF(3), 
a cyclic [3,0,3]3 enumerated code over GF(3) ]
</Example>
<!--
CyclicCodes(3,GF(3));
-->


<ManSection>
<Func Name="NrCyclicCodes" Arg=" n F "/>

<Description>
The function <C>NrCyclicCodes</C> calculates the number of 
cyclic codes of length <A>n</A> over field <A>F</A>.
</Description>
</ManSection>

<Example>
gap> NrCyclicCodes( 23, GF(2) );
8
gap> codelist := CyclicCodes( 23, GF(2) );
[ a cyclic [23,23,1]0 enumerated code over GF(2), 
  a cyclic [23,22,1..2]1 enumerated code over GF(2), 
  a cyclic [23,11,1..8]4..7 enumerated code over GF(2), 
  a cyclic [23,0,23]23 enumerated code over GF(2), 
  a cyclic [23,11,1..8]4..7 enumerated code over GF(2), 
  a cyclic [23,12,1..7]3 enumerated code over GF(2), 
  a cyclic [23,1,23]11 enumerated code over GF(2), 
  a cyclic [23,12,1..7]3 enumerated code over GF(2) ]
gap> BinaryGolayCode() in codelist;
true
gap> RepetitionCode( 23, GF(2) ) in codelist;
true
gap> CordaroWagnerCode( 23 ) in codelist;
false    # This code is not cyclic 
</Example>
<!--
NrCyclicCodes( 23, GF(2) );
codelist := CyclicCodes( 23, GF(2) );
BinaryGolayCode() in codelist;
RepetitionCode( 23, GF(2) ) in codelist;
CordaroWagnerCode( 23 ) in codelist;
-->

<ManSection>
	<Func Name="QuasiCyclicCode" Arg=" G s F "/>

	<Description>
		<C>QuasiCyclicCode( G, k, F )</C> generates a rate <M>1/m</M>
		quasi-cyclic code over field <A>F</A>. The input <A>G</A> is a list
		of univariate polynomials and <M>m</M> is the cardinality of this
		list. Note that <M>m</M> must be at least <M>2</M>.
		The input <A>s</A> is the size of each circulant and it may not
		necessarily be the same as the code dimension <M>k</M>, i.e.
		<M>k \le s</M>.
		<P/>
		There also exists another version, <C>QuasiCyclicCode( G, s )</C>
		which produces quasi-cyclic codes over <M>F_2</M> only. Here
		the parameter <A>s</A> holds the same definition and the input
		<A>G</A> is a list of integers, where each integer is
		an octal representation of a binary univariate polynomial.
	</Description>
</ManSection>

<Example>
gap> #
gap> # This example show the case for k = s
gap> #
gap> L1 := PolyCodeword( Codeword("10000000000", GF(4)) );
Z(2)^0
gap> L2 := PolyCodeword( Codeword("12223201000", GF(4)) );
x^7+Z(2^2)*x^5+Z(2^2)^2*x^4+Z(2^2)*x^3+Z(2^2)*x^2+Z(2^2)*x+Z(2)^0
gap> L3 := PolyCodeword( Codeword("31111220110", GF(4)) );
x^9+x^8+Z(2^2)*x^6+Z(2^2)*x^5+x^4+x^3+x^2+x+Z(2^2)^2
gap> L4 := PolyCodeword( Codeword("13320333010", GF(4)) );
x^9+Z(2^2)^2*x^7+Z(2^2)^2*x^6+Z(2^2)^2*x^5+Z(2^2)*x^3+Z(2^2)^2*x^2+Z(2^2)^2*x+\
Z(2)^0
gap> L5 := PolyCodeword( Codeword("20102211100", GF(4)) );
x^8+x^7+x^6+Z(2^2)*x^5+Z(2^2)*x^4+x^2+Z(2^2)
gap> C := QuasiCyclicCode( [L1, L2, L3, L4, L5], 11, GF(4) );
a linear [55,11,1..32]24..41 quasi-cyclic code over GF(4)
gap> MinimumDistance(C);
29
gap> Display(C);
a linear [55,11,29]24..41 quasi-cyclic code over GF(4)
gap> #
gap> # This example show the case for k &lt; s
gap> #
gap> L1 := PolyCodeword( Codeword("02212201220120211002000",GF(3)) );
-x^19+x^16+x^15-x^14-x^12+x^11-x^9-x^8+x^7-x^5-x^4+x^3-x^2-x
gap> L2 := PolyCodeword( Codeword("00221100200120220001110",GF(3)) );
x^21+x^20+x^19-x^15-x^14-x^12+x^11-x^8+x^5+x^4-x^3-x^2
gap> L3 := PolyCodeword( Codeword("22021011202221111020021",GF(3)) );
x^22-x^21-x^18+x^16+x^15+x^14+x^13-x^12-x^11-x^10-x^8+x^7+x^6+x^4-x^3-x-Z(3)^0
gap> C := QuasiCyclicCode( [L1, L2, L3], 23, GF(3) );
a linear [69,12,1..37]27..46 quasi-cyclic code over GF(3)
gap> MinimumDistance(C);
34
gap> Display(C);
a linear [69,12,34]27..46 quasi-cyclic code over GF(3)
gap> #
gap> # This example show the binary case using octal representation
gap> #
gap> L1 := 001;;   # 0 000 001
gap> L2 := 013;;   # 0 001 011
gap> L3 := 015;;   # 0 001 101
gap> L4 := 077;;   # 0 111 111
gap> C := QuasiCyclicCode( [L1, L2, L3, L4], 7 );
a linear [28,7,1..12]8..14 quasi-cyclic code over GF(2)
gap> MinimumDistance(C);
12
gap> Display(C);
a linear [28,7,12]8..14 quasi-cyclic code over GF(2)
</Example>
<!--
#
# This example show the case for k = s
#
L1 := PolyCodeword( Codeword("10000000000", GF(4)) );
L2 := PolyCodeword( Codeword("12223201000", GF(4)) );
L3 := PolyCodeword( Codeword("31111220110", GF(4)) );
L4 := PolyCodeword( Codeword("13320333010", GF(4)) );
L5 := PolyCodeword( Codeword("20102211100", GF(4)) );
C := QuasiCyclicCode( [L1, L2, L3, L4, L5], 11, GF(4) );
MinimumDistance(C);
Display(C);
#
# This example show the case for k &lt; s
#
L1 := PolyCodeword( Codeword("02212201220120211002000",GF(3)) );
L2 := PolyCodeword( Codeword("00221100200120220001110",GF(3)) );
L3 := PolyCodeword( Codeword("22021011202221111020021",GF(3)) );
C := QuasiCyclicCode( [L1, L2, L3], 23, GF(3) );
MinimumDistance(C);
Display(C);
#
# This example show the binary case using octal representation
#
L1 := 001;;   # 0 000 001
L2 := 013;;   # 0 001 011
L3 := 015;;   # 0 001 101
L4 := 077;;   # 0 111 111
C := QuasiCyclicCode( [L1, L2, L3, L4], 7 );
MinimumDistance(C);
Display(C);
-->


<ManSection>
	<Func Name="CyclicMDSCode" Arg=" q m k "/>

	<Description>
		Given the input parameters <A>q</A>, <A>m</A> and <A>k</A>,
		this function returns a <M>[q^m + 1, k, q^m - k + 2]</M>
		cyclic MDS code over GF(<M>q^m</M>). If <M>q^m</M> is even,
		any value of <M>k</M> can be used, otherwise only odd value
		of <M>k</M> is accepted.
	</Description>
</ManSection>	

<Example>
gap> C:=CyclicMDSCode(2,6,24);
a cyclic [65,24,42]31..41 MDS code over GF(64)
gap> IsMDSCode(C);
true
gap> C:=CyclicMDSCode(5,3,77);
a cyclic [126,77,50]35..49 MDS code over GF(125)
gap> IsMDSCode(C);
true
gap> C:=CyclicMDSCode(3,3,25);
a cyclic [28,25,4]2..3 MDS code over GF(27)
gap> GeneratorPol(C);
x^3+Z(3^3)^7*x^2+Z(3^3)^20*x-Z(3)^0
gap>
</Example>
<!--
C:=CyclicMDSCode(2,6,24);
IsMDSCode(C);
C:=CyclicMDSCode(5,3,77);
IsMDSCode(C);
C:=CyclicMDSCode(3,3,25);
GeneratorPol(C);
-->
<Index>MDS</Index>
<Index>cyclic</Index>


<ManSection>
	<Func Name="FourNegacirculantSelfDualCode" Arg=" ax bx k "/>

	<Description>
		A four-negacirculant self-dual code has a generator matrix
		<M>G</M> of the the following form

		<Verb>
    -                    -
    |        |  A  |  B  |
G = |  I_2k  |-----+-----|
    |        | -B^T| A^T |
    -                    -
		</Verb>
		where <M>AA^T + BB^T = -I_k</M> and <M>A</M>, <M>B</M> and
		their transposed are all <M>k \times k</M> negacirculant matrices.
		The generator matrix <M>G</M> returns a <M>[2k, k, d]_q</M>
		self-dual code over GF(<M>q</M>). For discussion on four-negacirculant
		self-dual codes, refer to <Cite Key="HHKK07"/>.
		<P/>
		The input parameters <A>ax</A> and <A>bx</A> are the defining
		polynomials over GF(<M>q</M>) of negacirculant matrices <M>A</M>
		and <M>B</M> respectively. The last parameter <A>k</A> is the
		dimension of the code.
	</Description>
</ManSection>

<Example>
gap> ax:=PolyCodeword(Codeword("1200200", GF(3)));
-x_1^4-x_1+Z(3)^0
gap> bx:=PolyCodeword(Codeword("2020221", GF(3)));
x_1^6-x_1^5-x_1^4-x_1^2-Z(3)^0
gap> C:=FourNegacirculantSelfDualCode(ax, bx, 14);;
gap> MinimumDistance(C);;
gap> CoveringRadius(C);;
gap> IsSelfDualCode(C);
true
gap> Display(C);
a linear [28,14,9]7 four-negacirculant self-dual code over GF(3)
gap> Display( GeneratorMat(C) );
 1 . . . . . . . . . . . . . 1 2 . . 2 . . 2 . 2 . 2 2 1
 . 1 . . . . . . . . . . . . . 1 2 . . 2 . 2 2 . 2 . 2 2
 . . 1 . . . . . . . . . . . . . 1 2 . . 2 1 2 2 . 2 . 2
 . . . 1 . . . . . . . . . . 1 . . 1 2 . . 1 1 2 2 . 2 .
 . . . . 1 . . . . . . . . . . 1 . . 1 2 . . 1 1 2 2 . 2
 . . . . . 1 . . . . . . . . . . 1 . . 1 2 1 . 1 1 2 2 .
 . . . . . . 1 . . . . . . . 1 . . 1 . . 1 . 1 . 1 1 2 2
 . . . . . . . 1 . . . . . . 1 1 2 2 . 2 . 1 . . 1 . . 1
 . . . . . . . . 1 . . . . . . 1 1 2 2 . 2 2 1 . . 1 . .
 . . . . . . . . . 1 . . . . 1 . 1 1 2 2 . . 2 1 . . 1 .
 . . . . . . . . . . 1 . . . . 1 . 1 1 2 2 . . 2 1 . . 1
 . . . . . . . . . . . 1 . . 1 . 1 . 1 1 2 2 . . 2 1 . .
 . . . . . . . . . . . . 1 . 1 1 . 1 . 1 1 . 2 . . 2 1 .
 . . . . . . . . . . . . . 1 2 1 1 . 1 . 1 . . 2 . . 2 1
gap> ax:=PolyCodeword(Codeword("013131000", GF(7)));
x_1^5+Z(7)*x_1^4+x_1^3+Z(7)*x_1^2+x_1
gap> bx:=PolyCodeword(Codeword("425435030", GF(7)));
Z(7)*x_1^7+Z(7)^5*x_1^5+Z(7)*x_1^4+Z(7)^4*x_1^3+Z(7)^5*x_1^2+Z(7)^2*x_1+Z(7)^4
gap> C:=FourNegacirculantSelfDualCodeNC(ax, bx, 18);
a linear [36,18,1..13]0..36 four-negacirculant self-dual code over GF(7)
gap> IsSelfDualCode(C);
true
</Example>

<!--
ax:=PolyCodeword(Codeword("1200200", GF(3)));
bx:=PolyCodeword(Codeword("2020221", GF(3)));
C:=FourNegacirculantSelfDualCode(ax, bx, 14);;
MinimumDistance(C);;
CoveringRadius(C);;
IsSelfDualCode(C);
Display(C);
Display( GeneratorMat(C) );
ax:=PolyCodeword(Codeword("013131000", GF(7)));
bx:=PolyCodeword(Codeword("425435030", GF(7)));
C:=FourNegacirculantSelfDualCodeNC(ax, bx, 18);
IsSelfDualCode(C);
-->
<Index>self-dual</Index>

<ManSection>
	<Func Name="FourNegacirculantSelfDualCodeNC" Arg=" ax bx k "/>
	<Description>
		This function is the same as <C>FourNegacirculantSelfDualCode</C>,
		except this version is faster as it does not estimate the minimum
		distance and covering radius of the code.
	</Description>
</ManSection>

</Section>

<Section>
<Heading>
Evaluation Codes
</Heading>
<Label Name="Evaluation Codes"/>


<Index>
code, evaluation
</Index>


<ManSection>
<Func Name="EvaluationCode" Arg=" P L R "/>

<Description>
Input: <A>F</A> is a finite field, 
<A>L</A> is a list of rational functions in
<M>R=F[x_1,...,x_r]</M>, <A>P</A> is a list of <M>n</M> points in 
<M>F^r</M> at which all of the functions in <A>L</A>
are defined. 
<Br/>
Output: The 'evaluation code' <M>C</M>, which is the image of the
evalation map
<Display>
Eval_P:span(L)\rightarrow F^n,
</Display> given by <M>f\longmapsto (f(p_1),...,f(p_n))</M>,
where <M>P=\{p_1,...,p_n\}</M> and <M>f \in L</M>.
The generator matrix of <M>C</M> is
<M>G=(f_i(p_j))_{f_i\in L,p_j\in P}</M>.
<P/>
This command returns a "record" object <C>C</C>
with several extra components (type <C>NamesOfComponents(C)</C>
to see them all): <C>C!.EvaluationMat</C> (not the same
as the generator matrix in general),
<C>C!.points</C> (namely <A>P</A>),
<C>C!.basis</C> (namely <A>L</A>), and
<C>C!.ring</C> (namely <A>R</A>). 
</Description>
</ManSection>

<Example>
gap> F:=GF(11);
GF(11)
gap> R := PolynomialRing(F,2);;
gap> indets := IndeterminatesOfPolynomialRing(R);;
gap> x:=indets[1];; y:=indets[2];;
gap> L:=[x^2*y,x*y,x^5,x^4,x^3,x^2,x,x^0];;
gap> Pts:=[ [ Z(11)^9, Z(11) ], [ Z(11)^8, Z(11) ], [ Z(11)^7, 0*Z(11) ],
   [ Z(11)^6, 0*Z(11) ], [ Z(11)^5, 0*Z(11) ], [ Z(11)^4, 0*Z(11) ],
   [ Z(11)^3, Z(11) ], [ Z(11)^2, 0*Z(11) ], [ Z(11), 0*Z(11) ], 
   [ Z(11)^0, 0*Z(11) ], [ 0*Z(11), Z(11) ] ];;
gap> C:=EvaluationCode(Pts,L,R);
a linear [11,8,1..3]2..3  evaluation code over GF(11)
gap> MinimumDistance(C);
3

</Example>
<!--
F:=GF(11);
R := PolynomialRing(F,["x","y"]);
indets := IndeterminatesOfPolynomialRing(R);;
x:=indets[1];; y:=indets[2];;
L:=[x^2*y,x*y,x^5,x^4,x^3,x^2,x,x^0];;
Pts:=[ [ Z(11)^9, Z(11) ], [ Z(11)^8, Z(11) ], [ Z(11)^7, 0*Z(11) ],
   [ Z(11)^6, 0*Z(11) ], [ Z(11)^5, 0*Z(11) ], [ Z(11)^4, 0*Z(11) ],
   [ Z(11)^3, Z(11) ], [ Z(11)^2, 0*Z(11) ], [ Z(11), 0*Z(11) ], 
   [ Z(11)^0, 0*Z(11) ], [ 0*Z(11), Z(11) ] ];;
C:=EvaluationCode(P,L,R);
MinimumDistance(C);
-->


<ManSection>
<Func Name="GeneralizedReedSolomonCode" Arg=" P k R "/>

<Description>
Input: R=F[x], where <A>F</A> is a finite field, 
<A>k</A> is a positive integer, 
<A>P</A> is a list of <M>n</M> points in <M>F</M>. 
<Br/>
Output: The <M>C</M> which is the image of the
evaluation map
<Display>
Eval_P:F[x]_k\rightarrow F^n,
</Display> 
given by <M>f\longmapsto (f(p_1),...,f(p_n))</M>,
where <M>P=\{p_1,...,p_n\}\subset F</M> and <M>f</M> ranges over the
space <M>F[x]_k</M> of all
polynomials of degree less than <M>k</M>.
<P/>
This command returns a "record" object <C>C</C>
with several extra components (type <C>NamesOfComponents(C)</C>
to see them all): <C>C!.points</C> (namely <A>P</A>),
<C>C!.degree</C> (namely <A>k</A>), and
<C>C!.ring</C> (namely <A>R</A>).
<P/>
This code can be decoded using <C>Decodeword</C>,
which applies the special decoder method (the
interpolation method), or using
<C>GeneralizedReedSolomonDecoderGao</C>
which applies an algorithm of S. Gao
(see <Ref Func="GeneralizedReedSolomonDecoderGao" Style="Number"/>).
This code has a special decoder record which implements
the interpolation algorithm described in section 5.2 of Justesen and Hoholdt 
<Cite Key="JH04"/>. See
<Ref Func="Decode" Style="Number"/> and
<Ref Func="Decodeword" Style="Number"/> for more details.
<P/>
The weighted version has implemented with the option
<C>GeneralizedReedSolomonCode(P,k,R,wts)</C>,
where <M>wts = [v_1, ..., v_n]</M> is a sequence of <M>n</M> 
non-zero elements from the base field <M>F</M> of <A>R</A>. 
See also the generalized Reed--Solomon code <M>GRS_k(P, V)</M> described 
in <Cite Key="MS83"/>, p.303.

<P/>
The list-decoding algorithm of Sudan-Guraswami
(described in section 12.1 of <Cite Key="JH04"/>) has
been implemented for generalized Reed-Solomon codes. 
See <Ref Func="GeneralizedReedSolomonListDecoder" Style="Number"/>.

</Description>
</ManSection>

<Example>
gap> R:=PolynomialRing(GF(11),["t"]);
GF(11)[t]
gap> P:=List([1,3,4,5,7],i->Z(11)^i);
[ Z(11), Z(11)^3, Z(11)^4, Z(11)^5, Z(11)^7 ]
gap> C:=GeneralizedReedSolomonCode(P,3,R);
a linear [5,3,1..3]2  generalized Reed-Solomon code over GF(11)
gap> MinimumDistance(C);
3
gap> V:=[Z(11)^0,Z(11)^0,Z(11)^0,Z(11)^0,Z(11)];
[ Z(11)^0, Z(11)^0, Z(11)^0, Z(11)^0, Z(11) ]
gap> C:=GeneralizedReedSolomonCode(P,3,R,V);
a linear [5,3,1..3]2  weighted generalized Reed-Solomon code over GF(11)
gap> MinimumDistance(C);
3
</Example>
<!--
R:=PolynomialRing(GF(11),["t"]);
P:=List([1,3,4,5,7],i->Z(11)^i);
C:=GeneralizedReedSolomonCode(P,3,R);
MinimumDistance(C);
V:=[Z(11)^0,Z(11)^0,Z(11)^0,Z(11)^0,Z(11)];
C:=GeneralizedReedSolomonCode(P,3,R,V);
MinimumDistance(C);
-->

See <Ref Func="EvaluationCode" Style="Number"/>
for a more general construction.

<ManSection>
<Func Name="GeneralizedReedMullerCode" Arg=" Pts r F "/>

<Description>
<C>GeneralizedReedMullerCode</C> returns a 'Reed-Muller code' 
<M>C</M>  with length <M>|Pts|</M> and order <M>r</M>.
 One considers (a) a basis of monomials 
for the vector space over <M>F=GF(q)</M>
of all polynomials in <M>F[x_1,...,x_d]</M> of degree
at most <M>r</M>, and (b) a set <M>Pts</M> of points in
<M>F^d</M>. The generator matrix of the associated 
<E>Reed-Muller code</E> <M>C</M> is <M>G=(f(p))_{f\in B,p \in Pts}</M>.
This code <M>C</M> is constructed using the command
<C>GeneralizedReedMullerCode(Pts,r,F)</C>.
When <M>Pts</M> is the set of all <M>q^d</M> points in <M>F^d</M>
then the command <C>GeneralizedReedMuller(d,r,F)</C> yields the code.
When <M>Pts</M> is the set of all <M>(q-1)^d</M> points with no
coordinate equal to <M>0</M> then this is can be constructed
using the <C>ToricCode</C> command (as a special case).
<P/>
This command returns a "record" object <C>C</C>
with several extra components (type <C>NamesOfComponents(C)</C>
to see them all): <C>C!.points</C> (namely <A>Pts</A>) and
<C>C!.degree</C> (namely <A>r</A>). 
</Description>
</ManSection>

<Example>
gap> Pts:=ToricPoints(2,GF(5));
[ [ Z(5)^0, Z(5)^0 ], [ Z(5)^0, Z(5) ], [ Z(5)^0, Z(5)^2 ], [ Z(5)^0, Z(5)^3 ],
  [ Z(5), Z(5)^0 ], [ Z(5), Z(5) ], [ Z(5), Z(5)^2 ], [ Z(5), Z(5)^3 ],
  [ Z(5)^2, Z(5)^0 ], [ Z(5)^2, Z(5) ], [ Z(5)^2, Z(5)^2 ], [ Z(5)^2, Z(5)^3 ],
  [ Z(5)^3, Z(5)^0 ], [ Z(5)^3, Z(5) ], [ Z(5)^3, Z(5)^2 ], [ Z(5)^3, Z(5)^3 ] ]
gap> C:=GeneralizedReedMullerCode(Pts,2,GF(5));
a linear [16,6,1..11]6..10  generalized Reed-Muller code over GF(5)
</Example>

See <Ref Func="EvaluationCode" Style="Number"/>
for a more general construction.


<ManSection>
<Func Name="ToricPoints" Arg=" n F "/>

<Description>
<C>ToricPoints(n,F)</C> returns the points in <M>(F^{\times})^n</M>.
</Description>
</ManSection>

<Example>
gap> ToricPoints(2,GF(5));
[ [ Z(5)^0, Z(5)^0 ], [ Z(5)^0, Z(5) ], [ Z(5)^0, Z(5)^2 ], 
  [ Z(5)^0, Z(5)^3 ], [ Z(5), Z(5)^0 ], [ Z(5), Z(5) ], [ Z(5), Z(5)^2 ], 
  [ Z(5), Z(5)^3 ], [ Z(5)^2, Z(5)^0 ], [ Z(5)^2, Z(5) ], [ Z(5)^2, Z(5)^2 ], 
  [ Z(5)^2, Z(5)^3 ], [ Z(5)^3, Z(5)^0 ], [ Z(5)^3, Z(5) ], 
  [ Z(5)^3, Z(5)^2 ], [ Z(5)^3, Z(5)^3 ] ]
</Example>
<!--
ToricPoints(2,GF(5));
-->


<Index>
code, toric
</Index>


<ManSection>
<Func Name="ToricCode" Arg=" L F "/>

<Description>
This function returns the toric codes as in 
D. Joyner <Cite Key="Jo04"/> (see also J. P. Hansen
<Cite Key="Han99"/>). This is a truncated (generalized) Reed-Muller code. 
Here <A>L</A> is a list of integral vectors and <A>F</A> 
is the finite field. The size of <A>F</A> must
be different from <M>2</M>.
<P/>
This command returns a record object <C>C</C>
with an extra component (type <C>NamesOfComponents(C)</C>
to see them all): <C>C!.exponents</C> (namely <A>L</A>).
</Description>
</ManSection>

<Example>
gap> C:=ToricCode([[1,0],[3,4]],GF(3));
a linear [4,1,4]2 toric code over GF(3)
gap> Display(GeneratorMat(C));
 1 1 2 2
gap> Elements(C);
[ [ 0 0 0 0 ], [ 1 1 2 2 ], [ 2 2 1 1 ] ]
</Example>
<!--
C:=ToricCode([[1,0],[3,4]],GF(3));
Display(GeneratorMat(C));
Elements(C);
-->

See <Ref Func="EvaluationCode" Style="Number"/>
for a more general construction.

</Section>

<Section>
<Heading>
Algebraic geometric codes
</Heading>
<Label Name="Algebraic geometric codes"/>


<Index>
code, AG
</Index>

Certain <Package>GUAVA</Package> functions related
to algebraic geometric codes are described in this 
section.

<ManSection>
<Func Name="AffineCurve" Arg ="poly, ring"/>

<Description>
This function simply defines the data structure of an affine plane
curve. In <Package>GUAVA</Package>, an affine curve is
a record <A>crv</A> having two components: a polynomial
<A>poly</A>, accessed in <Package>GUAVA</Package> 
by <A>crv.polynomial</A>,
and a polynomial ring over a field <M>F</M> in two variables <A>ring</A>,
accessed in <Package>GUAVA</Package> by <A>crv.ring</A>, 
containing <A>poly</A>.
You use this function to define a curve in 
<Package>GUAVA</Package>.
<P/>
For example, for the ring, one could take
<M>{\mathbb{Q}}[x,y]</M>, and for the polynomial
one could take <M>f(x,y)=x^2+y^2-1</M>. For the affine
line, simply taking <M>{\mathbb{Q}}[x,y]</M> for the
ring and <M>f(x,y)=y</M> for the polynomial.
<P/>
(Not sure if <M>F</M> neeeds to be a field in fact ...)
<P/>
To compute its degree, simply use the
<Ref Func="DegreeMultivariatePolynomial" Style="Number"/>
command.
</Description>

</ManSection>

<Example>
gap>
gap> F:=GF(11);;
gap> R2:=PolynomialRing(F,2);
PolynomialRing(..., [ x_1, x_2 ])
gap> vars:=IndeterminatesOfPolynomialRing(R2);;
gap> x:=vars[1];; y:=vars[2];;
gap> poly:=y;; crvP1:=AffineCurve(poly,R2);
rec( ring := PolynomialRing(..., [ x_1, x_2 ]), polynomial := x_2 )
gap> degree_crv:=DegreeMultivariatePolynomial(poly,R2);
1
gap> poly:=y^2-x*(x^2-1);; ell_crv:=AffineCurve(poly,R2);
rec( ring := PolynomialRing(..., [ x_1, x_2 ]), polynomial := -x_1^3+x_2^2+x_1 )
gap> degree_crv:=DegreeMultivariatePolynomial(poly,R2);
3
gap> poly:=x^2+y^2-1;; circle:=AffineCurve(poly,R2);
rec( ring := PolynomialRing(..., [ x_1, x_2 ]), polynomial := x_1^2+x_2^2-Z(11)^0 )
gap> degree_crv:=DegreeMultivariatePolynomial(poly,R2);
2
gap> q:=3;;
gap> F:=GF(q^2);;
gap> R:=PolynomialRing(F,2);;
gap> vars:=IndeterminatesOfPolynomialRing(R);
[ x_1, x_2 ]
gap> x:=vars[1];
x_1
gap> y:=vars[2];
x_2
gap> crv:=AffineCurve(y^q+y-x^(q+1),R);
rec( ring := PolynomialRing(..., [ x_1, x_2 ]), polynomial := -x_1^4+x_2^3+x_2 )
gap>
</Example>
<!--
F:=GF(11);;
R2:=PolynomialRing(F,2);
vars:=IndeterminatesOfPolynomialRing(R2);;
x:=vars[1];; y:=vars[2];;
poly:=y;; crvP1:=AffineCurve(poly,R2);
degree_crv:=DegreeMultivariatePolynomial(poly,R2);
poly:=y^2-x*(x^2-1);; ell_crv:=AffineCurve(poly,R2);
degree_crv:=DegreeMultivariatePolynomial(poly,R2);
poly:=x^2+y^2-1;; circle:=AffineCurve(poly,R2);
degree_crv:=DegreeMultivariatePolynomial(poly,R2);
q:=3;
F:=GF(q^2);
R:=PolynomialRing(F,2);;
vars:=IndeterminatesOfPolynomialRing(R);
x:=vars[1];
y:=vars[2];
crv:=AffineCurve(y^q+y-x^(q+1),R);
-->

In GAP, a <E>point</E> 
<Index>point</Index>
on a curve defined by <M>f(x,y)=0</M>
is simply a list <A>[a,b]</A> of elements of <M>F</M> 
satisfying this polynomial equation.


<ManSection>
<Func Name="AffinePointsOnCurve" Arg=" f R E "/>

<Description>
<C>AffinePointsOnCurve(f,R,E)</C> returns the points 
<M>(x,y) \in E^2</M> satisying <M>f(x,y)=0</M>,
where <A>f</A> is an element of <M>R=F[x,y]</M>.
</Description>
</ManSection>

<Example>
gap> F:=GF(11);;
gap> R := PolynomialRing(F,["x","y"]);
PolynomialRing(..., [ x, y ])
gap> indets := IndeterminatesOfPolynomialRing(R);;
gap> x:=indets[1];; y:=indets[2];;
gap> P:=AffinePointsOnCurve(y^2-x^11+x,R,F);
[ [ Z(11)^9, 0*Z(11) ], [ Z(11)^8, 0*Z(11) ], [ Z(11)^7, 0*Z(11) ], 
  [ Z(11)^6, 0*Z(11) ], [ Z(11)^5, 0*Z(11) ], [ Z(11)^4, 0*Z(11) ], 
  [ Z(11)^3, 0*Z(11) ], [ Z(11)^2, 0*Z(11) ], [ Z(11), 0*Z(11) ], 
  [ Z(11)^0, 0*Z(11) ], [ 0*Z(11), 0*Z(11) ] ]
</Example>
<!--
F:=GF(11);;
R := PolynomialRing(F,["x","y"]);
indets := IndeterminatesOfPolynomialRing(R);;
x:=indets[1];; y:=indets[2];;
P:=AffinePointsOnCurve(y^2-x^11+x,R,F);
-->

<ManSection>
<Func Name="GenusCurve" Arg ="crv"/>

<Description>
If <A>crv</A> represents <M>f(x,y)=0</M>, where
<M>f</M> is a polynomial of degree <M>d</M>,
then this function simply returns <M>(d-1)(d-2)/2</M>.
At the present, the function does not check if 
the curve is singular (in which case the result
may be false).
</Description>
</ManSection>

<Example>
gap> q:=4;;
gap> F:=GF(q^2);;
gap> a:=X(F);;
gap> R1:=PolynomialRing(F,[a]);;
gap> var1:=IndeterminatesOfPolynomialRing(R1);;
gap> b:=X(F);;
gap> R2:=PolynomialRing(F,[a,b]);;
gap> var2:=IndeterminatesOfPolynomialRing(R2);;
gap> crv:=AffineCurve(b^q+b-a^(q+1),R2);;
gap> crv:=AffineCurve(b^q+b-a^(q+1),R2);
rec( ring := PolynomialRing(..., [ x_1, x_1 ]), polynomial := x_1^5+x_1^4+x_1 )
gap> GenusCurve(crv);
36

</Example>

<ManSection>
<Func Name="GOrbitPoint " Arg ="G,P "/>

<Description>
<A>P</A> must be a point in projective space <M>\mathbb{P}^n(F)</M>,
<A>G</A> must be a finite subgroup of <M>GL(n+1,F)</M>,
This function  returns all (representatives of projective)
points in the orbit <M>G\cdot P</M>.
<P/>
The example below computes the orbit of the automorphism group 
on the Klein quartic over the field
<M>GF(43)</M> on the ``point at infinity''. 
</Description>
</ManSection>

<Example>
gap> R:= PolynomialRing( GF(43), 3 );;
gap> vars:= IndeterminatesOfPolynomialRing(R);;
gap> x:= vars[1];; y:= vars[2];; z:= vars[3];;
gap> zz:=Z(43)^6;
Z(43)^6
gap> zzz:=Z(43);
Z(43)
gap> rho1:=zz^0*[[zz^4,0,0],[0,zz^2,0],[0,0,zz]];
[ [ Z(43)^24, 0*Z(43), 0*Z(43) ], 
[ 0*Z(43), Z(43)^12, 0*Z(43) ], 
[ 0*Z(43), 0*Z(43), Z(43)^6 ] ]
gap> rho2:=zz^0*[[0,1,0],[0,0,1],[1,0,0]];
[ [ 0*Z(43), Z(43)^0, 0*Z(43) ], 
[ 0*Z(43), 0*Z(43), Z(43)^0 ], 
[ Z(43)^0, 0*Z(43), 0*Z(43) ] ]
gap> rho3:=(-1)*[[(zz-zz^6 )/zzz^7,( zz^2-zz^5 )/ zzz^7, ( zz^4-zz^3 )/ zzz^7],
>             [( zz^2-zz^5 )/ zzz^7, ( zz^4-zz^3 )/ zzz^7, ( zz-zz^6 )/ zzz^7],
>             [( zz^4-zz^3 )/ zzz^7, ( zz-zz^6 )/ zzz^7, ( zz^2-zz^5 )/ zzz^7]];
[ [ Z(43)^9, Z(43)^28, Z(43)^12 ], 
[ Z(43)^28, Z(43)^12, Z(43)^9 ], 
[ Z(43)^12, Z(43)^9, Z(43)^28 ] ]
gap> G:=Group([rho1,rho2,rho3]);; #PSL(2,7)
gap> Size(G);
168
gap> P:=[1,0,0]*zzz^0;
[ Z(43)^0, 0*Z(43), 0*Z(43) ]
gap> O:=GOrbitPoint(G,P);
[ [ Z(43)^0, 0*Z(43), 0*Z(43) ], [ 0*Z(43), Z(43)^0, 0*Z(43) ], 
[ 0*Z(43), 0*Z(43), Z(43)^0 ], [ Z(43)^0, Z(43)^39, Z(43)^16 ], 
[ Z(43)^0, Z(43)^33, Z(43)^28 ], [ Z(43)^0, Z(43)^27, Z(43)^40 ],
[ Z(43)^0, Z(43)^21, Z(43)^10 ], [ Z(43)^0, Z(43)^15, Z(43)^22 ], 
[ Z(43)^0, Z(43)^9, Z(43)^34 ], [ Z(43)^0, Z(43)^3, Z(43)^4 ], 
[ Z(43)^3, Z(43)^22, Z(43)^6 ], [ Z(43)^3, Z(43)^16, Z(43)^18 ],
[ Z(43)^3, Z(43)^10, Z(43)^30 ], [ Z(43)^3, Z(43)^4, Z(43)^0 ], 
[ Z(43)^3, Z(43)^40, Z(43)^12 ], [ Z(43)^3, Z(43)^34, Z(43)^24 ], 
[ Z(43)^3, Z(43)^28, Z(43)^36 ], [ Z(43)^4, Z(43)^30, Z(43)^27 ],
[ Z(43)^4, Z(43)^24, Z(43)^39 ], [ Z(43)^4, Z(43)^18, Z(43)^9 ], 
[ Z(43)^4, Z(43)^12, Z(43)^21 ], [ Z(43)^4, Z(43)^6, Z(43)^33 ], 
[ Z(43)^4, Z(43)^0, Z(43)^3 ], [ Z(43)^4, Z(43)^36, Z(43)^15 ] ]
gap> Length(O);
24

</Example>

Informally, a <E>divisor</E> 
<Index>divisor</Index>
on a curve is a formal integer linear combination of points
on the curve, <M>D=m_1P_1+...+m_kP_k</M>,
where the <M>m_i</M> are integers (the ``multiplicity'' of 
<M>P_i</M> in <M>D</M>) and <M>P_i</M> are (<M>F</M>-rational) 
points on the affine plane curve. 
In other words, a divisor is an element of the free 
abelian group generated by the <M>F</M>-rational affine 
points on the curve. The <E>support</E>
<Index>support</Index>
of a divisor <M>D</M> is simply the set of points
which occurs in the sum defining <M>D</M> with 
non-zero ``multiplicity''.
The data structure for a divisor on an affine plane curve
is a record having the following components:
<List>
<Item>
the coefficients (the integer weights of the points in the support), 
</Item>
<Item>
the support,
</Item>
<Item>
the curve, itself a record which has components:
polynomial and polynomial ring.
</Item>
</List>
<P/>

<P/>


<ManSection>
<Func Name="DivisorOnAffineCurve" Arg ="cdiv,sdiv,crv"/>

<Description>
This is the command you use to define a divisor in 
<Package>GUAVA</Package>. Of course,
<A>crv</A> is the curve on which the divisor lives,
<A>cdiv</A> is the list of coefficients (or ``multiplicities''),
<A>sdiv</A> is the list of points on <A>crv</A> in the support.

<Example>
gap> q:=5;
5
gap> F:=GF(q);
GF(5)
gap> R:=PolynomialRing(F,2);;
gap> vars:=IndeterminatesOfPolynomialRing(R);
[ x_1, x_2 ]
gap> x:=vars[1];
x_1
gap> y:=vars[2];
x_2
gap> crv:=AffineCurve(y^3-x^3-x-1,R);
rec( ring := PolynomialRing(..., [ x_1, x_2 ]), 
     polynomial := -x_1^3+x_2^3-x_1-Z(5)^0 )
gap> Pts:=AffinePointsOnCurve(crv,R,F);;
gap> supp:=[Pts[1],Pts[2]];
[ [ 0*Z(5), Z(5)^0 ], [ Z(5)^0, Z(5) ] ]
gap> D:=DivisorOnAffineCurve([1,-1],supp,crv);
rec( coeffs := [ 1, -1 ], 
     support := [ [ 0*Z(5), Z(5)^0 ], [ Z(5)^0, Z(5) ] ],
     curve := rec( ring := PolynomialRing(..., [ x_1, x_2 ]), 
                   polynomial := -x_1^3+x_2^3-x_1-Z(5)^0 ) )

</Example>
<!--
q:=5;
F:=GF(q);
R:=PolynomialRing(F,2);;
vars:=IndeterminatesOfPolynomialRing(R);
x:=vars[1];
y:=vars[2];
crv:=AffineCurve(y^3-x^3-x-1,R);
Pts:=PointsOnAffineCurve(crv,F);;
supp:=[Pts[1],Pts[2]];
D:=DivisorOnAffineCurve([1,-1],supp,crv);
-->

</Description>
</ManSection>

<ManSection>
<Func Name="DivisorAddition " Arg ="D1,D2 "/>

<Description>
If <M>D_1=m_1P_1+...+m_kP_k</M>
and <M>D_2=n_1P_1+...+n_kP_k</M> are divisors then
<M>D_1+D_2=(m_1+n_1)P_1+...+(m_k+n_k)P_k</M>.

</Description>
</ManSection>


<ManSection>
<Func Name="DivisorDegree " Arg ="D "/>

<Description>
If <M>D=m_1P_1+...+m_kP_k</M> is a divisor then the <E>degree</E>
<Index>degree</Index> 
is <M>m_1+...+m_k</M>.
</Description>
</ManSection>

<ManSection>
<Func Name="DivisorNegate " Arg ="D "/>

<Description>
Self-explanatory.
</Description>
</ManSection>



<ManSection>
<Func Name="DivisorIsZero " Arg ="D "/>

<Description>
Self-explanatory.

</Description>
</ManSection>

<ManSection>
<Func Name="DivisorsEqual " Arg ="D1,D2 "/>

<Description>
Self-explanatory.

</Description>
</ManSection>

<ManSection>
<Func Name="DivisorGCD " Arg ="D1,D2 "/>

<Description>
If <M>m=p_1^{e_1}...p_k^{e_k}</M>
and <M>n=p_1^{f_1}...p_k^{f_k}</M> are two integers then their
greatest common divisor is 
<M>GCD(m,n)=p_1^{min(e_1,f_1)}...p_k^{min(e_k,f_k)}</M>.
A similar definition works for two divisors on a curve.
If <M>D_1=e_1P_1+...+e_kP_k</M>
and <M>D_2n=f_1P_1+...+f_kP_k</M> are two divisors on a curve then their
<E>greatest common divisor</E>
<Index>greatest common divisor</Index> 
is  <M>GCD(m,n)=min(e_1,f_1)P_1+...+min(e_k,f_k)P_k</M>.
This function computes this quantity.


</Description>
</ManSection>

<ManSection>
<Func Name="DivisorLCM " Arg ="D1,D2 "/>

<Description>
If <M>m=p_1^{e_1}...p_k^{e_k}</M>
and <M>n=p_1^{f_1}...p_k^{f_k}</M> are two integers then their
least common multiple is 
<M>LCM(m,n)=p_1^{max(e_1,f_1)}...p_k^{max(e_k,f_k)}</M>.
A similar definition works for two divisors on a curve.
If <M>D_1=e_1P_1+...+e_kP_k</M>
and <M>D_2=f_1P_1+...+f_kP_k</M> are two divisors on a curve then their
<E>least common multiple</E>
<Index>least common multiple</Index> 
is  <M>LCM(m,n)=max(e_1,f_1)P_1+...+max(e_k,f_k)P_k</M>.
This function computes this quantity.

<Example>
gap> F:=GF(11);
GF(11)
gap> R1:=PolynomialRing(F,["a"]);;
gap> var1:=IndeterminatesOfPolynomialRing(R1);; a:=var1[1];;
gap> b:=X(F,"b",var1);
b
gap> var2:=Concatenation(var1,[b]);
[ a, b ]
gap> R2:=PolynomialRing(F,var2);
PolynomialRing(..., [ a, b ])
gap> crvP1:=AffineCurve(b,R2);
rec( ring := PolynomialRing(..., [ a, b ]), polynomial := b )
gap> div1:=DivisorOnAffineCurve([1,2,3,4],[Z(11)^2,Z(11)^3,Z(11)^7,Z(11)],crvP1);
rec( coeffs := [ 1, 2, 3, 4 ], 
     support := [ Z(11)^2, Z(11)^3, Z(11)^7, Z(11) ], 
     curve := rec( ring := PolynomialRing(..., [ a, b ]), polynomial := b ) )
gap> DivisorDegree(div1);
10
gap> div2:=DivisorOnAffineCurve([1,2,3,4],[Z(11),Z(11)^2,Z(11)^3,Z(11)^4],crvP1);
rec( coeffs := [ 1, 2, 3, 4 ], 
     support := [ Z(11), Z(11)^2, Z(11)^3, Z(11)^4 ], 
     curve := rec( ring := PolynomialRing(..., [ a, b ]), polynomial := b ) )
gap> DivisorDegree(div2);
10
gap> div3:=DivisorAddition(div1,div2);
rec( coeffs := [ 5, 3, 5, 4, 3 ], 
     support := [ Z(11), Z(11)^2, Z(11)^3, Z(11)^4, Z(11)^7 ], 
     curve := rec( ring := PolynomialRing(..., [ a, b ]), polynomial := b ) )
gap> DivisorDegree(div3);
20
gap> DivisorIsEffective(div1);
true
gap> DivisorIsEffective(div2);
true
gap>
gap> ndiv1:=DivisorNegate(div1);
rec( coeffs := [ -1, -2, -3, -4 ], 
     support := [ Z(11)^2, Z(11)^3, Z(11)^7, Z(11) ], 
     curve := rec( ring := PolynomialRing(..., [ a, b ]), polynomial := b ) )
gap> zdiv:=DivisorAddition(div1,ndiv1);
rec( coeffs := [ 0, 0, 0, 0 ], 
     support := [ Z(11), Z(11)^2, Z(11)^3, Z(11)^7 ], 
     curve := rec( ring := PolynomialRing(..., [ a, b ]), polynomial := b ) )
gap> DivisorIsZero(zdiv);
true
gap> div_gcd:=DivisorGCD(div1,div2);
rec( coeffs := [ 1, 1, 2, 0, 0 ], 
     support := [ Z(11), Z(11)^2, Z(11)^3, Z(11)^4, Z(11)^7 ], 
     curve := rec( ring := PolynomialRing(..., [ a, b ]), polynomial := b ) )
gap> div_lcm:=DivisorLCM(div1,div2);
rec( coeffs := [ 4, 2, 3, 4, 3 ], 
     support := [ Z(11), Z(11)^2, Z(11)^3, Z(11)^4, Z(11)^7 ], 
     curve := rec( ring := PolynomialRing(..., [ a, b ]), polynomial := b ) )
gap> DivisorDegree(div_gcd);
4
gap> DivisorDegree(div_lcm);
16
gap> DivisorEqual(div3,DivisorAddition(div_gcd,div_lcm));
true

</Example>
<!--
F:=GF(11);
R1:=PolynomialRing(F,["a"]);;
var1:=IndeterminatesOfPolynomialRing(R1);; a:=var1[1];;
b:=X(F,"b",var1);
var2:=Concatenation(var1,[b]);
R2:=PolynomialRing(F,var2);
crvP1:=AffineCurve(b,R2);
div1:=DivisorOnAffineCurve([1,2,3,4],[Z(11)^2,Z(11)^3,Z(11)^7,Z(11)],crvP1);
DivisorDegree(div1);
div2:=DivisorOnAffineCurve([1,2,3,4],[Z(11),Z(11)^2,Z(11)^3,Z(11)^4],crvP1);
DivisorDegree(div2);
div3:=DivisorAddition(div1,div2);
DivisorDegree(div3);
DivisorIsEffective(div1);
DivisorIsEffective(div2);
ndiv1:=DivisorNegate(div1);
zdiv:=DivisorAddition(div1,ndiv1);
DivisorIsZero(zdiv);
div_gcd:=DivisorGCD(div1,div2);
div_lcm:=DivisorLCM(div1,div2);
DivisorDegree(div_gcd);
DivisorDegree(div_lcm);
DivisorEqual(div3,DivisorAddition(div_gcd,div_lcm));
-->

</Description>
</ManSection>

Let <M>G</M> denote a finite subgroup of <M>PGL(2,F)</M> and let 
<M>D</M> denote a divisor on the projective line <M>\mathbb{P}^1(F)</M>.
If <M>G</M> leaves <M>D</M> unchanged (it may permute the
points in the support of <M>D</M> but must preserve 
their sum in <M>D</M>) then the Riemann-Roch space
<M>L(D)</M> is a <M>G</M>-module. The commands in this section help explore
the <M>G</M>-module structure of <M>L(D)</M> in the case then the ground field
<M>F</M>  is finite.


<P/>

<ManSection>

<Func Name="RiemannRochSpaceBasisFunctionP1 " Arg ="P,k,R2 "/>

<Description>
 Input:
 <A>R2</A> is a polynomial ring in two variables, say <M>F[x,y]</M>;
<A>P</A> is an element of the base field, say <M>F</M>;
<A>k</A> is an integer.
Output: <M>1/(x-P)^k</M>

</Description>
</ManSection>


<ManSection>

<Func Name="DivisorOfRationalFunctionP1 " Arg ="f, R "/>

<Description>
 Here <M>R = F[x,y]</M> is a polynomial ring in
the variables <M>x,y</M> and <M>f</M> is a rational function of <M>x</M>.
Simply returns the principal divisor on <M>{\mathbb{P}}^1</M> 
associated to <M>f</M>.

<Example>

gap> F:=GF(11);
GF(11)
gap> R1:=PolynomialRing(F,["a"]);;
gap> var1:=IndeterminatesOfPolynomialRing(R1);; a:=var1[1];;
gap> b:=X(F,"b",var1);
b
gap> var2:=Concatenation(var1,[b]);
[ a, b ]
gap> R2:=PolynomialRing(F,var2);
PolynomialRing(..., [ a, b ])
gap> pt:=Z(11);
Z(11)
gap> f:=RiemannRochSpaceBasisFunctionP1(pt,2,R2);
(Z(11)^0)/(a^2+Z(11)^7*a+Z(11)^2)
gap> Df:=DivisorOfRationalFunctionP1(f,R2);
rec( coeffs := [ -2 ], support := [ Z(11) ], 
     curve := rec( ring := PolynomialRing(..., [ a, b ]), polynomial := a )
   )
gap> Df.support;
[ Z(11) ]
gap> F:=GF(11);;
gap> R:=PolynomialRing(F,2);;
gap> vars:=IndeterminatesOfPolynomialRing(R);;
gap> a:=vars[1];;
gap> b:=vars[2];;
gap> f:=(a^4+Z(11)^6*a^3-a^2+Z(11)^7*a+Z(11)^0)/(a^4+Z(11)*a^2+Z(11)^7*a+Z(11));;
gap> divf:=DivisorOfRationalFunctionP1(f,R);
rec( coeffs := [ 3, 1 ], support := [ Z(11), Z(11)^7 ],
  curve := rec( ring := PolynomialRing(..., [ a, b ]), polynomial := a ) )
gap> denf:=DenominatorOfRationalFunction(f); RootsOfUPol(denf);
a^4+Z(11)*a^2+Z(11)^7*a+Z(11)
[  ]
gap> numf:=NumeratorOfRationalFunction(f); RootsOfUPol(numf);
a^4+Z(11)^6*a^3-a^2+Z(11)^7*a+Z(11)^0
[ Z(11)^7, Z(11), Z(11), Z(11) ]

</Example>
<!--
F:=GF(11);
R1:=PolynomialRing(F,["a"]);;
var1:=IndeterminatesOfPolynomialRing(R1);; a:=var1[1];;
b:=X(F,"b",var1);
var2:=Concatenation(var1,[b]);
R2:=PolynomialRing(F,var2);
pt:=Z(11);
f:=RiemannRochSpaceBasisFunctionP1(pt,2,R2);
Df:=DivisorOfRationalFunctionP1(f,R2);
Df.support;
F:=GF(11);;
R:=PolynomialRing(F,2);;
vars:=IndeterminatesOfPolynomialRing(R);;
a:=vars[1];;
b:=vars[2];;
f:=(a^4+Z(11)^6*a^3-a^2+Z(11)^7*a+Z(11)^0)/(a^4+Z(11)*a^2+Z(11)^7*a+Z(11));;
divf:=DivisorOfRationalFunctionP1(f,R);
denf:=DenominatorOfRationalFunction(f); RootsOfUPol(denf);
numf:=NumeratorOfRationalFunction(f); RootsOfUPol(numf);
-->

</Description>
</ManSection>


<ManSection>

<Func Name="RiemannRochSpaceBasisP1 " Arg ="D "/>

<Description>

This returns the basis of the Riemann-Roch space <M>L(D)</M>
associated to the divisor <A>D</A> on the projective line
<M>{\mathbb{P}}^1</M>.

</Description>
</ManSection>

<Example>
gap> F:=GF(11);
GF(11)
gap> R1:=PolynomialRing(F,["a"]);;
gap> var1:=IndeterminatesOfPolynomialRing(R1);; a:=var1[1];;
gap> b:=X(F,"b",var1);
b
gap> var2:=Concatenation(var1,[b]);
[ a, b ]
gap> R2:=PolynomialRing(F,var2);
PolynomialRing(..., [ a, b ])
gap> crvP1:=AffineCurve(b,R2);
rec( ring := PolynomialRing(..., [ a, b ]), polynomial := b )
gap> D:=DivisorOnAffineCurve([1,2,3,4],[Z(11)^2,Z(11)^3,Z(11)^7,Z(11)],crvP1);
rec( coeffs := [ 1, 2, 3, 4 ], 
     support := [ Z(11)^2, Z(11)^3, Z(11)^7, Z(11) ], 
     curve := rec( ring := PolynomialRing(..., [ a, b ]), polynomial := b ) )
gap> B:=RiemannRochSpaceBasisP1(D);
[ Z(11)^0, (Z(11)^0)/(a+Z(11)^7), (Z(11)^0)/(a+Z(11)^8), 
(Z(11)^0)/(a^2+Z(11)^9*a+Z(11)^6), (Z(11)^0)/(a+Z(11)^2), 
(Z(11)^0)/(a^2+Z(11)^3*a+Z(11)^4), (Z(11)^0)/(a^3+a^2+Z(11)^2*a+Z(11)^6),
  (Z(11)^0)/(a+Z(11)^6), (Z(11)^0)/(a^2+Z(11)^7*a+Z(11)^2), 
(Z(11)^0)/(a^3+Z(11)^4*a^2+a+Z(11)^8), 
(Z(11)^0)/(a^4+Z(11)^8*a^3+Z(11)*a^2+a+Z(11)^4) ]
gap> DivisorOfRationalFunctionP1(B[1],R2).support;
[  ]
gap> DivisorOfRationalFunctionP1(B[2],R2).support;
[ Z(11)^2 ]
gap> DivisorOfRationalFunctionP1(B[3],R2).support;
[ Z(11)^3 ]
gap> DivisorOfRationalFunctionP1(B[4],R2).support;
[ Z(11)^3 ]
gap> DivisorOfRationalFunctionP1(B[5],R2).support;
[ Z(11)^7 ]
gap> DivisorOfRationalFunctionP1(B[6],R2).support;
[ Z(11)^7 ]
gap> DivisorOfRationalFunctionP1(B[7],R2).support;
[ Z(11)^7 ]
gap> DivisorOfRationalFunctionP1(B[8],R2).support;
[ Z(11) ]
gap> DivisorOfRationalFunctionP1(B[9],R2).support;
[ Z(11) ]
gap> DivisorOfRationalFunctionP1(B[10],R2).support;
[ Z(11) ]
gap> DivisorOfRationalFunctionP1(B[11],R2).support;
[ Z(11) ]

</Example>
<!--
F:=GF(11);
R1:=PolynomialRing(F,["a"]);;
var1:=IndeterminatesOfPolynomialRing(R1);; a:=var1[1];;
b:=X(F,"b",var1);
var2:=Concatenation(var1,[b]);
R2:=PolynomialRing(F,var2);
crvP1:=AffineCurve(b,R2);
D:=DivisorOnAffineCurve([1,2,3,4],[Z(11)^2,Z(11)^3,Z(11)^7,Z(11)],crvP1);
B:=RiemannRochSpaceBasisP1(D);
DivisorOfRationalFunctionP1(B[1],R2).support;
DivisorOfRationalFunctionP1(B[2],R2).support;
DivisorOfRationalFunctionP1(B[3],R2).support;
DivisorOfRationalFunctionP1(B[4],R2).support;
DivisorOfRationalFunctionP1(B[5],R2).support;
DivisorOfRationalFunctionP1(B[6],R2).support;
DivisorOfRationalFunctionP1(B[7],R2).support;
DivisorOfRationalFunctionP1(B[8],R2).support;
DivisorOfRationalFunctionP1(B[9],R2).support;
DivisorOfRationalFunctionP1(B[10],R2).support;
DivisorOfRationalFunctionP1(B[11],R2).support;
-->

<ManSection>

<Func Name="MoebiusTransformation " Arg ="A,R "/>

<Description>
The arguments are a <M>2\times 2</M> matrix <M>A</M> 
with entries in a field <M>F</M>
and a polynomial ring <A>R</A>of
one variable, say <M>F[x]</M>.
This function returns the linear fractional
transformatio associated to <A>A</A>.
These transformations can be composed with each other
using GAP's <C>Value</C> command.

</Description>
</ManSection>

<ManSection>

<Func Name="ActionMoebiusTransformationOnFunction " Arg ="A,f,R2 "/>

<Description>
The arguments are a <M>2\times 2</M> matrix <M>A</M> 
with entries in a field <M>F</M>, a rational function 
<A>f</A> of one variable, say in <M>F(x)</M>, 
and a polynomial ring <A>R2</A>, say <M>F[x,y]</M>.
This function simply returns the composition of the
function <A>f</A> with the M&#xf6;bius transformation
of <A>A</A>.
</Description>
</ManSection>

<ManSection>

<Func Name="ActionMoebiusTransformationOnDivisorP1 " Arg ="A,D "/>

<Description>
A M&#xf6;bius transformation may be regarded as an automorphism
of the projective line <M>\mathbb{P}^1</M>. This function simply 
returns the image of the divisor <A>D</A> under 
the M&#xf6;bius transformation defined by <A>A</A>,
provided that 
<C>IsActionMoebiusTransformationOnDivisorDefinedP1(A,D)</C>
returns true.


</Description>
</ManSection>

<ManSection>

<Func Name="IsActionMoebiusTransformationOnDivisorDefinedP1 " Arg ="A,D "/>

<Description>
Returns true of none of the points in the support of the
divisor <A>D</A> is the pole of the M&#xf6;bius transformation.
 
<Example>
gap> F:=GF(11);
GF(11)
gap> R1:=PolynomialRing(F,["a"]);;
gap> var1:=IndeterminatesOfPolynomialRing(R1);; a:=var1[1];;
gap> b:=X(F,"b",var1);
b
gap> var2:=Concatenation(var1,[b]);
[ a, b ]
gap> R2:=PolynomialRing(F,var2);
PolynomialRing(..., [ a, b ])
gap> crvP1:=AffineCurve(b,R2);
rec( ring := PolynomialRing(..., [ a, b ]), polynomial := b )
gap> D:=DivisorOnAffineCurve([1,2,3,4],[Z(11)^2,Z(11)^3,Z(11)^7,Z(11)],crvP1);
rec( coeffs := [ 1, 2, 3, 4 ], 
     support := [ Z(11)^2, Z(11)^3, Z(11)^7, Z(11) ], 
     curve := rec( ring := PolynomialRing(..., [ a, b ]), polynomial := b ) )
gap> A:=Z(11)^0*[[1,2],[1,4]];
[ [ Z(11)^0, Z(11) ], [ Z(11)^0, Z(11)^2 ] ]
gap> ActionMoebiusTransformationOnDivisorDefinedP1(A,D);
false
gap> A:=Z(11)^0*[[1,2],[3,4]];
[ [ Z(11)^0, Z(11) ], [ Z(11)^8, Z(11)^2 ] ]
gap> ActionMoebiusTransformationOnDivisorDefinedP1(A,D);
true
gap> ActionMoebiusTransformationOnDivisorP1(A,D);
rec( coeffs := [ 1, 2, 3, 4 ], 
     support := [ Z(11)^5, Z(11)^6, Z(11)^8, Z(11)^7 ], 
     curve := rec( ring := PolynomialRing(..., [ a, b ]), polynomial := b ) )
gap> f:=MoebiusTransformation(A,R1);
(a+Z(11))/(Z(11)^8*a+Z(11)^2)
gap> ActionMoebiusTransformationOnFunction(A,f,R1);
-Z(11)^0+Z(11)^3*a^-1

</Example>
<!--
F:=GF(11);
R1:=PolynomialRing(F,["a"]);;
var1:=IndeterminatesOfPolynomialRing(R1);; a:=var1[1];;
b:=X(F,"b",var1);
var2:=Concatenation(var1,[b]);
R2:=PolynomialRing(F,var2);
crvP1:=AffineCurve(b,R2);
D:=DivisorOnAffineCurve([1,2,3,4],[Z(11)^2,Z(11)^3,Z(11)^7,Z(11)],crvP1);
A:=Z(11)^0*[[1,2],[1,4]];
ActionMoebiusTransformationOnDivisorDefinedP1(A,D);
A:=Z(11)^0*[[1,2],[3,4]];
ActionMoebiusTransformationOnDivisorDefinedP1(A,D);
ActionMoebiusTransformationOnDivisorP1(A,D);
f:=MoebiusTransformation(A,R1);
ActionMoebiusTransformationOnFunction(A,f,R1);

-->
</Description>
</ManSection>

<ManSection>

<Func Name="DivisorAutomorphismGroupP1 " Arg ="D "/>

<Description>
Input: A divisor <A>D</A> on <M>\mathbb{P}^1(F)</M>,
where <M>F</M> is a finite field.
Output: A subgroup <M>Aut(D)\subset Aut(\mathbb{P}^1)</M>
preserving <A>D</A>.
<P/>
Very slow.

<Example>
gap> F:=GF(11);
GF(11)
gap> R1:=PolynomialRing(F,["a"]);;
gap> var1:=IndeterminatesOfPolynomialRing(R1);; a:=var1[1];;
gap> b:=X(F,"b",var1);
b
gap> var2:=Concatenation(var1,[b]);
[ a, b ]
gap> R2:=PolynomialRing(F,var2);
PolynomialRing(..., [ a, b ])
gap> crvP1:=AffineCurve(b,R2);
rec( ring := PolynomialRing(..., [ a, b ]), polynomial := b )
gap> D:=DivisorOnAffineCurve([1,2,3,4],[Z(11)^2,Z(11)^3,Z(11)^7,Z(11)],crvP1);
rec( coeffs := [ 1, 2, 3, 4 ], 
     support := [ Z(11)^2, Z(11)^3, Z(11)^7, Z(11) ], 
     curve := rec( ring := PolynomialRing(..., [ a, b ]), polynomial := b ) )
gap> agp:=DivisorAutomorphismGroupP1(D);; time;
7305
gap> IdGroup(agp);
[ 10, 2 ]

</Example>
<!--
F:=GF(11);
R1:=PolynomialRing(F,["a"]);;
var1:=IndeterminatesOfPolynomialRing(R1);; a:=var1[1];;
b:=X(F,"b",var1);
var2:=Concatenation(var1,[b]);
R2:=PolynomialRing(F,var2);
crvP1:=AffineCurve(b,R2);
D:=DivisorOnAffineCurve([1,2,3,4],[Z(11)^2,Z(11)^3,Z(11)^7,Z(11)],crvP1);
agp:=DivisorAutomorphismGroupP1(D);; time;
IdGroup(agp);
-->

</Description>
</ManSection>

<ManSection>

<Func Name="MatrixRepresentationOnRiemannRochSpaceP1 " Arg ="g,D "/>

<Description>
Input: An element <A>g</A> in <M>G</M>, a subgroup
of <M>Aut(D)\subset Aut(\mathbb{P}^1)</M>, and a divisor
<A>D</A> on <M>\mathbb{P}^1(F)</M>, where
<M>F</M> is a finite field.
Output: a <M>d\times d</M> matrix, where <M>d = dim\, L(D)</M>,
representing the action of <A>g</A> on <M>L(D)</M>.
<P/>
Note: <A>g</A> sends <M>L(D)</M> to <M>r\cdot L(D)</M>, where
<M>r</M> is a polynomial of degree <M>1</M> depending on 
<A>g</A> and <A>D</A>.
<P/>
Also very slow.
<P/>
The GAP command <C>BrauerCharacterValue</C> 
can be used to ``lift'' the eigenvalues of this
matrix to the complex numbers.

<P/>

<Example>
gap> F:=GF(11);
GF(11)
gap> R1:=PolynomialRing(F,["a"]);;
gap> var1:=IndeterminatesOfPolynomialRing(R1);; a:=var1[1];;
gap> b:=X(F,"b",var1);
b
gap> var2:=Concatenation(var1,[b]);
[ a, b ]
gap> R2:=PolynomialRing(F,var2);
PolynomialRing(..., [ a, b ])
gap> crvP1:=AffineCurve(b,R2);
rec( ring := PolynomialRing(..., [ a, b ]), polynomial := b )
gap> D:=DivisorOnAffineCurve([1,1,1,4],[Z(11)^2,Z(11)^3,Z(11)^7,Z(11)],crvP1);
rec( coeffs := [ 1, 1, 1, 4 ],  
     support := [ Z(11)^2, Z(11)^3, Z(11)^7, Z(11) ], 
     curve := rec( ring := PolynomialRing(..., [ a, b ]), polynomial := b ) )
gap> agp:=DivisorAutomorphismGroupP1(D);; time;
7198
gap> IdGroup(agp);
[ 20, 5 ]
gap> g:=Random(agp);
[ [ Z(11)^4, Z(11)^9 ], [ Z(11)^0, Z(11)^9 ] ]
gap> rho:=MatrixRepresentationOnRiemannRochSpaceP1(g,D);
[ [ Z(11)^0, 0*Z(11), 0*Z(11), 0*Z(11), 0*Z(11), 0*Z(11), 0*Z(11), 0*Z(11) ], 
[ Z(11)^0, 0*Z(11), 0*Z(11), Z(11), 0*Z(11), 0*Z(11), 0*Z(11), 0*Z(11) ],
  [ Z(11)^7, 0*Z(11), Z(11)^5, 0*Z(11), 0*Z(11), 0*Z(11), 0*Z(11), 0*Z(11) ], 
[ Z(11)^4, Z(11)^9, 0*Z(11), 0*Z(11), 0*Z(11), 0*Z(11), 0*Z(11), 0*Z(11) ],
  [ Z(11)^2, 0*Z(11), 0*Z(11), 0*Z(11), Z(11)^5, 0*Z(11), 0*Z(11), 0*Z(11) ], 
[ Z(11)^4, 0*Z(11), 0*Z(11), 0*Z(11), Z(11)^8, Z(11)^0, 0*Z(11), 0*Z(11) ],
  [ Z(11)^6, 0*Z(11), 0*Z(11), 0*Z(11), Z(11)^7, Z(11)^0, Z(11)^5, 0*Z(11) ], 
[ Z(11)^8, 0*Z(11), 0*Z(11), 0*Z(11), Z(11)^3, Z(11)^3, Z(11)^9, Z(11)^0 ] ]
gap> Display(rho);
  1  .  .  .  .  .  .  .
  1  .  .  2  .  .  .  .
  7  . 10  .  .  .  .  .
  5  6  .  .  .  .  .  .
  4  .  .  . 10  .  .  .
  5  .  .  .  3  1  .  .
  9  .  .  .  7  1 10  .
  3  .  .  .  8  8  6  1

</Example>

</Description>
</ManSection>
<!--
F:=GF(11);
R1:=PolynomialRing(F,["a"]);;
var1:=IndeterminatesOfPolynomialRing(R1);; a:=var1[1];;
b:=X(F,"b",var1);
var2:=Concatenation(var1,[b]);
R2:=PolynomialRing(F,var2);
crvP1:=AffineCurve(b,R2);
D:=DivisorOnAffineCurve([1,1,1,4],[Z(11)^2,Z(11)^3,Z(11)^7,Z(11)],crvP1);
agp:=DivisorAutomorphismGroupP1(D);; time;
IdGroup(agp);
g:=Random(agp);
rho:=MatrixRepresentationOnRiemannRochSpaceP1(g,D);
Display(rho);
Eigenvalues(F,rho);
charpoly:=CharacteristicPolynomail(rho);
Factors(charpoly);
JordanDecomposition(rho);

-->

<!--
<ManSection>
<Func Name="XingLingCode" Arg=" k R "/>

<Description>
Input: An integer <M>k<M> and a polynomial ring in one
variable <M>R=F[x]<M>.
<Br/>
Output: The associated Xing-Ling code.
<P/>
For a reference, see .....
</Description>
</ManSection>

<Example>

F:=GF(11);;
R:=PolynomialRing(F,1);;
vars:=IndeterminatesOfPolynomialRing(R);;
a:=vars[1];;
C:=XingLingCode(25,R);

F:=GF(3);;
R:=PolynomialRing(F,1);;
vars:=IndeterminatesOfPolynomialRing(R);;
a:=vars[1];;
C:=XingLingCode(7,R);
MinimumDistance(C);


F:=GF(4);;
R:=PolynomialRing(F,1);;
vars:=IndeterminatesOfPolynomialRing(R);;
a:=vars[1];;
C:=XingLingCode(9,R);
MinimumDistance(C);

F:=GF(7);;
R:=PolynomialRing(F,1);;
vars:=IndeterminatesOfPolynomialRing(R);;
a:=vars[1];;
C:=XingLingCode(15,R);
MinimumDistance(C);
</Example>
-->


<ManSection>
<Func Name="GoppaCodeClassical" Arg=" div pts "/>

<Description>
Input: A divisor <A>div</A> on the projective line
<M>{\mathbb{P}}^1(F)</M> over a finite field <M>F</M>
and a list <A>pts</A> of points <M>\{P_1,...,P_n\}\subset F</M> 
disjoint from the support of <A>div</A>.
<Br/>
Output: The classical (evaluation) Goppa code associated
to this data. This is the code 

<Display>
C=\{(f(P_1),...,f(P_n))\ |\ f\in L(D)_F\}.
</Display>

</Description>
</ManSection>

<Example>
gap> F:=GF(11);;
gap> R2:=PolynomialRing(F,2);;
gap> vars:=IndeterminatesOfPolynomialRing(R2);;
gap> a:=vars[1];;b:=vars[2];;
gap> cdiv:=[ 1, 2, -1, -2 ];
[ 1, 2, -1, -2 ]
gap> sdiv:=[ Z(11)^2, Z(11)^3, Z(11)^6, Z(11)^9 ];
[ Z(11)^2, Z(11)^3, Z(11)^6, Z(11)^9 ]
gap> crv:=rec(polynomial:=b,ring:=R2);
rec( polynomial := x_2, ring := PolynomialRing(..., [ x_1, x_2 ]) )
gap> div:=DivisorOnAffineCurve(cdiv,sdiv,crv);
rec( coeffs := [ 1, 2, -1, -2 ], support := [ Z(11)^2, Z(11)^3, Z(11)^6, Z(11)^9 ],
  curve := rec( polynomial := x_2, ring := PolynomialRing(..., [ x_1, x_2 ]) ) )
gap> pts:=Difference(Elements(GF(11)),div.support);
[ 0*Z(11), Z(11)^0, Z(11), Z(11)^4, Z(11)^5, Z(11)^7, Z(11)^8 ]
gap> C:=GoppaCodeClassical(div,pts);
a linear [7,2,1..6]4..5 code defined by generator matrix over GF(11)
gap> MinimumDistance(C);
6
</Example>
<!--
F:=GF(11);;
R2:=PolynomialRing(F,2);;
vars:=IndeterminatesOfPolynomialRing(R2);; 
a:=vars[1];;b:=vars[2];;
cdiv:=[ 1, 2, -1, -2 ];
sdiv:=[ Z(11)^2, Z(11)^3, Z(11)^6, Z(11)^9 ];
crv:=rec(polynomial:=b,ring:=R2);
div:=DivisorOnAffineCurve(cdiv,sdiv,crv);
pts:=Difference(Elements(GF(11)),div.support);
C:=GoppaCodeClassical(div,pts);
MinimumDistance(C);

-->



<ManSection>
<Func Name="EvaluationBivariateCode" Arg=" pts L crv"/>

<Description>
Input: <C>pts</C> is a set of affine points on <C>crv</C>,
<C>L</C> is a list of rational functions on <C>crv</C>.
<Br/>
Output: The evaluation code associated to the points
in <C>pts</C> and functions in <C>L</C>,
but specifically for affine plane curves
and this function 
checks if points are "bad" (if so removes them
from the list <C>pts</C> automatically).
A point is ``bad'' if either it does not lie on the
set of non-singular <M>F</M>-rational points 
(places of degree 1) on the curve.
<P/>
Very similar to <C>EvaluationCode</C>
(see <Ref Func="EvaluationCode" Style="Number"/>
for a more general construction).

</Description>
</ManSection>

<ManSection>
<Func Name="EvaluationBivariateCodeNC" Arg=" pts L crv "/>

<Description>
As in <C>EvaluationBivariateCode</C> but does not
check if the points are ``bad''.
<P/>
Input: <C>pts</C> is a set of affine points on <C>crv</C>,
<C>L</C> is a list of rational functions on <C>crv</C>. 
<Br/>
Output: The evaluation code associated to the points
in <C>pts</C> and functions in <C>L</C>.


</Description>
</ManSection>

<Example>
gap> q:=4;;
gap> F:=GF(q^2);;
gap> R:=PolynomialRing(F,2);;
gap> vars:=IndeterminatesOfPolynomialRing(R);;
gap> x:=vars[1];;
gap> y:=vars[2];;
gap> crv:=AffineCurve(y^q+y-x^(q+1),R);
rec( ring := PolynomialRing(..., [ x_1, x_2 ]), polynomial := x_1^5+x_2^4+x_2 )
gap> L:=[ x^0, x, x^2*y^-1 ];
[ Z(2)^0, x_1, x_1^2/x_2 ]
gap> Pts:=AffinePointsOnCurve(crv.polynomial,crv.ring,F);;
gap> C1:=EvaluationBivariateCode(Pts,L,crv); time;


 Automatically removed the following 'bad' points (either a pole or not 
 on the curve):
[ [ 0*Z(2), 0*Z(2) ] ]

a linear [63,3,1..60]51..59  evaluation code over GF(16)
52
gap> P:=Difference(Pts,[[ 0*Z(2^4)^0, 0*Z(2)^0 ]]);;
gap> C2:=EvaluationBivariateCodeNC(P,L,crv); time;
a linear [63,3,1..60]51..59  evaluation code over GF(16)
48
gap> C3:=EvaluationCode(P,L,R); time;
a linear [63,3,1..56]51..59  evaluation code over GF(16)
58
gap> MinimumDistance(C1);
56
gap> MinimumDistance(C2);
56
gap> MinimumDistance(C3);
56
gap>
</Example>
<!--
q:=4;;
F:=GF(q^2);;
R:=PolynomialRing(F,2);;
vars:=IndeterminatesOfPolynomialRing(R);;
x:=vars[1];;
y:=vars[2];;
crv:=AffineCurve(y^q+y-x^(q+1),R);
L:=[ x^0, x, x^2*y^-1 ];
Pts:=AffinePointsOnCurve(crv.polynomial,crv.ring,F);;
C1:=EvaluationBivariateCode(Pts,L,crv); time;
P:=Difference(Pts,[[ 0*Z(2^4)^0, 0*Z(2)^0 ]]);;
C2:=EvaluationBivariateCodeNC(P,L,crv); time;
C3:=EvaluationCode(P,L,R); time;
MinimumDistance(C1);
MinimumDistance(C2);
MinimumDistance(C3);
-->


<ManSection>
<Func Name="OnePointAGCode" Arg=" f P m R "/>

<Description>
Input: <A>f</A> is a polynomial in R=F[x,y], where
<A>F</A> is a finite field, 
<A>m</A> is a positive integer (the multiplicity of the 
`point at infinity' <M>\infty</M> on the curve <M>f(x,y)=0</M>), 
<A>P</A> is a list of <M>n</M> points on the curve over <M>F</M>. 
<Br/>
Output: The <M>C</M> which is the image of the
evaluation map
<Display>
Eval_P:L(m \cdot \infty)\rightarrow F^n,
</Display> 
given by <M>f\longmapsto (f(p_1),...,f(p_n))</M>,
where <M>p_i \in P</M>.
Here <M>L(m \cdot \infty)</M> denotes the Riemann-Roch 
space of the divisor <M>m \cdot \infty</M> on the curve.
This has a basis consisting of monomials
<M>x^iy^j</M>, where <M>(i,j)</M> range over a 
polygon depending on <M>m</M> and <M>f(x,y)</M>.
For more details on the Riemann-Roch 
space of the divisor <M>m \cdot \infty</M> see 
Proposition III.10.5 in Stichtenoth <Cite Key="St93"/>.
<P/>
This command returns a "record" object <C>C</C>
with several extra components (type <C>NamesOfComponents(C)</C>
to see them all): <C>C!.points</C> (namely <A>P</A>),
<C>C!.multiplicity</C> (namely <A>m</A>), 
<C>C!.curve</C> (namely <A>f</A>) and
<C>C!.ring</C> (namely <A>R</A>).
</Description>
</ManSection>

<Example>
gap> F:=GF(11);
GF(11)
gap> R := PolynomialRing(F,["x","y"]);
PolynomialRing(..., [ x, y ])
gap> indets := IndeterminatesOfPolynomialRing(R);
[ x, y ]
gap> x:=indets[1]; y:=indets[2];
x
y
gap> P:=AffinePointsOnCurve(y^2-x^11+x,R,F);;
gap> C:=OnePointAGCode(y^2-x^11+x,P,15,R);
a linear [11,8,1..0]2..3  one-point AG code over GF(11)
gap> MinimumDistance(C);
4
gap> Pts:=List([1,2,4,6,7,8,9,10,11],i->P[i]);;
gap> C:=OnePointAGCode(y^2-x^11+x,PT,10,R);
a linear [9,6,1..4]2..3 one-point AG code over GF(11)
gap> MinimumDistance(C);
4
</Example>
<!--
F:=GF(11);
R := PolynomialRing(F,["x","y"]);
indets := IndeterminatesOfPolynomialRing(R);
x:=indets[1]; y:=indets[2];
P:=AffinePointsOnCurve(y^2-x^11+x,R,F);;
C:=OnePointAGCode(y^2-x^11+x,P,15,R);
MinimumDistance(C);
Pts:=List([1,2,4,6,7,8,9,10,11],i->P[i]);;
C:=OnePointAGCode(y^2-x^11+x,Pts,10,R);
MinimumDistance(C);
-->

See <Ref Func="EvaluationCode" Style="Number"/>
for a more general construction.

</Section>


<Section>
<Heading>
Low-Density Parity-Check Codes
</Heading>
<Label Name="LDPC"/>

<Index>
LDPC
</Index>

Low-density parity-check (LDPC) codes form a class of linear
block codes whose parity-check matrix--as the name implies,
is sparse. LDPC codes were introduced by Robert Gallager
in 1962 <Cite Key="Gallager.1962"/> as his PhD work. Due to
the decoding complexity for the technology back then, these
codes were forgotten. Not until the late 1990s, these codes
were rediscovered and research results have shown that LDPC
codes can achieve near Shannon's capacity performance provided
that their block length is long enough and soft-decision
iterative decoder is employed. Note that the bit-flipping
decoder (see <C>BitFlipDecoder</C>) is a hard-decision
decoder and hence capacity achieving performance cannot
be achieved despite having a large block length.
<P/>

Based on the structure of their parity-check matrix, LDPC
codes may be categorised into two classes:
<List>
	<Item>
		Regular LDPC codes
		<P/>
		This class of codes has a fixed number of non zeros
		per column and per row in their parity-check matrix.
		These codes are usually denoted as <M>(n,j,k)</M>
		codes where <M>n</M> is the block length, <M>j</M>
		is the number of non zeros per column in their
		parity-check matrix and <M>k</M> is the number of
		non zeros per row in their parity-check matrix.
	</Item>
	<Item>
		Irregular LDPC codes
		<P/>
		The irregular codes, on the other hand, do not have
		a fixed number of non zeros per column and row in
		their parity-check matrix. This class of codes are
		commonly represented by two polynomials which denote
		the distribution of the number of non zeros in the
		columns and rows respectively of their parity-check
		matrix.
	</Item>
</List>
		
<ManSection>
<Func Name="QCLDPCCodeFromGroup" Arg=" m j k "/>

<Description>
	<C>QCLDCCodeFromGroup</C> produces an <M>(n,j,k)</M> regular
	quasi-cyclic LDPC code over GF(2) of block length <M>n = mk</M>.
	The term quasi-cyclic in the context of LDPC codes typically
	refers to LDPC codes whose parity-check matrix <M>H</M> has
	the following form
		<Verb>
    -                                              -
    |  I_P(0,0)  |  I_P(0,1)  | ... |  I_P(0,k-1)  |
    |  I_P(1,0)  |  I_P(1,1)  | ... |  I_P(1,k-1)  |
H = |      .     |     .      |  .  |       .      |,
    |      .     |     .      |  .  |       .      |
    | I_P(j-1,0) | I_P(j-1,1) | ... | I_P(j-1,k-1) |
    -                                              -
		</Verb>
	where <M>I_{P(s,t)}</M> is an identity matrix of size
	<M>m \times m</M> which has been shifted so that the
	<M>1</M> on the first row starts at position <M>P(s,t)</M>.
	<P/>

	Let <M>F</M> be a multiplicative group of integers modulo
	<M>m</M>. If <M>m</M> is a prime, <M>F=\{0,1,...,m-1\}</M>,
	otherwise <M>F</M> contains a set of integers which are
	relatively prime to <M>m</M>. In both cases, the order
	of <M>F</M> is equal to <M>\phi(m)</M>. Let <M>a</M> and
	<M>b</M> be non zeros of <M>F</M> such that the orders
	of <M>a</M> and <M>b</M> are <M>k</M> and <M>j</M>
	respectively. Note that the integers <M>a</M> and <M>b</M>
	can always be found provided that <M>k</M> and <M>j</M>
	respectively divide <M>\phi(m)</M>. Having obtain integers
	<M>a</M> and <M>b</M>, construct the following <M>j \times k</M>
	matrix <M>P</M> so that the element at row <M>s</M> and
	column <M>t</M> is given by <M>P(s,t) = a^tb^s</M>, i.e.
		<Verb>
    -                                             -
    |    1    |     a    | . . . |      a^{k-1}   |
    |    b    |    ab    | . . . |     a^{k-1}b   |
P = |    .    |    .     |   .   |        .       |.
    |    .    |    .     |   .   |        .       |
    | b^{j-1} | ab^{j-1} | . . . | a^{k-1}b^{j-1} |
    -                                             -
		</Verb>
	The parity-check matrix <M>H</M> of the LDPC code can be
	obtained by replacing each element of matrix <M>P</M>, i.e.
	<M>P(s,t)</M>, with an identity matrix <M>I_{P(s,t)}</M>
	of size <M>m \times m</M>.
	<P/>

	The code rate <M>R</M> of the constructed code is given by
	<Display>
		R \geq 1 - \frac{j}{k}
	</Display>
	where the sign <M>\geq</M> is due to the possible
	existence of some non linearly independent rows in <M>H</M>.
	For more details, refer to the paper by Tanner et al
	<Cite Key="TSSFC04"/>.
</Description>
</ManSection>

<Example>
gap> C := QCLDPCCodeFromGroup(7,2,3);
a linear [21,8,1..6]5..10 low-density parity-check code over GF(2)
gap> MinimumWeight(C);
[21,8] linear code over GF(2) - minimum weight evaluation
Known lower-bound: 1
There are 3 generator matrices, ranks : 8 8 5 
The weight of the minimum weight codeword satisfies 0 mod 2 congruence
Enumerating codewords with information weight 1 (w=1)
    Found new minimum weight 6
Number of matrices required for codeword enumeration 2
Completed w= 1, 24 codewords enumerated, lower-bound 4, upper-bound 6
Termination expected with information weight 2 at matrix 1
-----------------------------------------------------------------------------
Enumerating codewords with information weight 2 (w=2) using 1 matrices
Completed w= 2, 28 codewords enumerated, lower-bound 6, upper-bound 6
-----------------------------------------------------------------------------
Minimum weight: 6
6
gap> # The quasi-cyclic structure is obvious from the check matrix
gap> Display( CheckMat(C) );
 1 . . . . . . . 1 . . . . . . . . 1 . . .
 . 1 . . . . . . . 1 . . . . . . . . 1 . .
 . . 1 . . . . . . . 1 . . . . . . . . 1 .
 . . . 1 . . . . . . . 1 . . . . . . . . 1
 . . . . 1 . . . . . . . 1 . 1 . . . . . .
 . . . . . 1 . . . . . . . 1 . 1 . . . . .
 . . . . . . 1 1 . . . . . . . . 1 . . . .
 . . . . . 1 . . . . . 1 . . . . 1 . . . .
 . . . . . . 1 . . . . . 1 . . . . 1 . . .
 1 . . . . . . . . . . . . 1 . . . . 1 . .
 . 1 . . . . . 1 . . . . . . . . . . . 1 .
 . . 1 . . . . . 1 . . . . . . . . . . . 1
 . . . 1 . . . . . 1 . . . . 1 . . . . . .
 . . . . 1 . . . . . 1 . . . . 1 . . . . .
gap> # This is the famous [155,64,20] quasi-cyclic LDPC codes
gap> C := QCLDPCCodeFromGroup(31,3,5);
a linear [155,64,1..24]24..77 low-density parity-check code over GF(2)
gap> # An example using non prime m, it may take a while to construct this code
gap> C := QCLDPCCodeFromGroup(356,4,8);
a linear [2848,1436,1..120]312..1412 low-density parity-check code over GF(2)
</Example>
<!--
C := QCLDPCCodeFromGroup(7,2,3);
MinimumWeight(C);
# The quasi-cyclic structure is obvious from the check matrix
Display( CheckMat(C) );
# This is the famous [155,64,20] quasi-cyclic LDPC codes
C := QCLDPCCodeFromGroup(31,3,5);
# An example using non prime m, it may take a while to construct this code
C := QCLDPCCodeFromGroup(356,4,8);
-->

</Section>


</Chapter>


<Chapter>
<Heading>Manipulating Codes</Heading>
<Label Name="Manipulating Codes"/>

In this chapter we describe several functions 
<Package>GUAVA</Package> uses to manipulate
codes. Some of the best codes are obtained by starting with for example a
BCH code, and manipulating it.
<P/>
In some cases, it is faster to perform calculations with a manipulated
code than to use the original code. For example, if the dimension of the
code is larger than half the word length,  it is generally faster to
compute the weight distribution by first calculating the weight
distribution of the dual code than by directly calculating the weight
distribution of the original code.  The size of the dual code is smaller
in these cases.
<P/>
Because <Package>GUAVA</Package> keeps all information in a 
code record, in some cases the information can be preserved 
after manipulations.   Therefore, computations do not always have 
to start from scratch.
<P/>
In Section
<Ref Label="Functions that Generate a New Code from a Given Code" Style="Number"/>,
we describe functions that take a code with certain parameters, modify it in
some way and return a different code (see 
<Ref Func="ExtendedCode" Style="Number"/>,
<Ref Func="PuncturedCode" Style="Number"/>, 
<Ref Func="EvenWeightSubcode" Style="Number"/>,  
<Ref Func="PermutedCode" Style="Number"/>,  
<Ref Func="ExpurgatedCode" Style="Number"/>,
<Ref Func="AugmentedCode" Style="Number"/>,       
<Ref Func="RemovedElementsCode" Style="Number"/>,  
<Ref Func="AddedElementsCode" Style="Number"/>,
<Ref Func="ShortenedCode" Style="Number"/>,  
<Ref Func="LengthenedCode" Style="Number"/>,  
<Ref Func="ResidueCode" Style="Number"/>,  
<Ref Func="ConstructionBCode" Style="Number"/>,
<Ref Func="DualCode" Style="Number"/>,  
<Ref Func="ConversionFieldCode" Style="Number"/>,        
<Ref Func="ConstantWeightSubcode" Style="Number"/>,
<Ref Func="StandardFormCode" Style="Number"/> and 
<Ref Func="CosetCode" Style="Number"/>).

In Section
<Ref Label="Functions that Generate a New Code from Two or More Given Codes" Style="Number"/>,  
we describe functions that generate a new code out of two codes (see
<Ref Func="DirectSumCode" Style="Number"/>, 
<Ref Func="UUVCode" Style="Number"/>, 
<Ref Func="DirectProductCode" Style="Number"/>,  
<Ref Func="IntersectionCode" Style="Number"/>  and
<Ref Func="UnionCode" Style="Number"/>).

<Section>
<Heading>
Functions that Generate a New Code from a Given Code
</Heading>
<Label Name="Functions that Generate a New Code from a Given Code"/>

<Index>
Parity check
</Index>

<ManSection>
<Func Name="ExtendedCode" Arg=" C [i] "/>

<Description>
<C>ExtendedCode</C>  extends the code <A>C</A> <A>i</A> times and
returns the result. <A>i</A> is equal to <M>1</M> by default. 
Extending is done by adding a parity check bit after the 
last coordinate.  The coordinates of all codewords now add up to zero. 
In the binary case,  each codeword has even weight.
<P/>
The word length increases by <A>i</A>. The size of the code remains the
same. In the binary case, the minimum distance increases by one if it was
odd. In other cases, that is not always true.
<P/>
A cyclic code in general is no longer cyclic after extending.
</Description>
</ManSection>

<Example>
gap> C1 := HammingCode( 3, GF(2) );
a linear [7,4,3]1 Hamming (3,2) code over GF(2)
gap> C2 := ExtendedCode( C1 );
a linear [8,4,4]2 extended code
gap> IsEquivalent( C2, ReedMullerCode( 1, 3 ) );
true
gap> List( AsSSortedList( C2 ), WeightCodeword );
[ 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8 ]
gap> C3 := EvenWeightSubcode( C1 );
a linear [7,3,4]2..3 even weight subcode 
</Example>
<!--
C1 := HammingCode( 3, GF(2) );
C2 := ExtendedCode( C1 );
IsEquivalent( C2, ReedMullerCode( 1, 3 ) );
List( AsSSortedList( C2 ), WeightCodeword );
C3 := EvenWeightSubcode( C1 );
-->

To undo extending, call <C>PuncturedCode</C> (see 
<Ref Func="PuncturedCode" Style="Number"/>).  The
function <C>EvenWeightSubcode</C> (see  
<Ref Func="EvenWeightSubcode" Style="Number"/>) also returns a
related code with only even weights, but without changing its word
length.

<ManSection>
<Func Name="PuncturedCode" Arg=" C "/>

<Description>
<C>PuncturedCode</C> punctures <A>C</A> in the last column, 
and returns the result. Puncturing is done simply by cutting 
off the last column from each codeword. This means the word length 
decreases by one. The minimum distance in general also decrease by one.
<P/>
This command can also be called with the syntax
<C>PuncturedCode( C, L )</C>. In this case,
<C>PuncturedCode</C> punctures <A>C</A> in the columns 
specified by <A>L</A>, a list of integers.  
All columns specified by <A>L</A> are omitted from each codeword.
If <M>l</M> is the length of <A>L</A> (so the number of removed 
columns), the word length decreases by <M>l</M>. The minimum 
distance can also decrease by <M>l</M> or less.
<P/>
Puncturing a cyclic code in general results in a non-cyclic code. If the
code is  punctured in all the columns where a word of minimal weight is
unequal to zero, the dimension of the resulting code decreases.
</Description>
</ManSection>

<Example>
gap> C1 := BCHCode( 15, 5, GF(2) );
a cyclic [15,7,5]3..5 BCH code, delta=5, b=1 over GF(2)
gap> C2 := PuncturedCode( C1 );
a linear [14,7,4]3..5 punctured code
gap> ExtendedCode( C2 ) = C1;
false
gap> PuncturedCode( C1, [1,2,3,4,5,6,7] );
a linear [8,7,1]1 punctured code
gap> PuncturedCode( WholeSpaceCode( 4, GF(5) ) );
a linear [3,3,1]0 punctured code  # The dimension decreased from 4 to 3 
</Example>
<!--
C1 := BCHCode( 15, 5, GF(2) );
C2 := PuncturedCode( C1 );
ExtendedCode( C2 ) = C1;
PuncturedCode( C1, [1,2,3,4,5,6,7] );
PuncturedCode( WholeSpaceCode( 4, GF(5) ) );
-->

<C>ExtendedCode</C> extends the code again (see 
<Ref Func="ExtendedCode" Style="Number"/>),
although in general this does not result in the old code.

<ManSection>
<Func Name="EvenWeightSubcode" Arg=" C "/>

<Description>
<C>EvenWeightSubcode</C> returns the even weight subcode 
of <A>C</A>, consisting of all codewords of <A>C</A> with even 
weight. If <A>C</A> is a linear code and
contains words of odd weight, the resulting code  has a dimension of one
less.  The minimum distance always increases with one if it was odd. If
<A>C</A> is a binary cyclic code, and <M>g(x)</M> is its 
generator polynomial, the even weight subcode either has 
generator polynomial <M>g(x)</M> (if <M>g(x)</M> is
divisible by  <M>x-1</M>) or <M>g(x)\cdot (x-1)</M> 
(if no factor <M>x-1</M> was present in <M>g(x)</M>).
So the even weight subcode is again cyclic.
<P/>
Of course, if all codewords of <A>C</A> are already of even weight,  
the returned code is equal to <A>C</A>.
</Description>
</ManSection>

<Example>
gap> C1 := EvenWeightSubcode( BCHCode( 8, 4, GF(3) ) );
an (8,33,4..8)3..8 even weight subcode
gap> List( AsSSortedList( C1 ), WeightCodeword );
[ 0, 4, 4, 4, 4, 4, 4, 6, 4, 4, 4, 4, 6, 4, 4, 6, 4, 4, 8, 6, 4, 6, 8, 4, 4, 
  4, 6, 4, 6, 8, 4, 6, 8 ]
gap> EvenWeightSubcode( ReedMullerCode( 1, 3 ) );
a linear [8,4,4]2 Reed-Muller (1,3) code over GF(2) 
</Example>
<!--
C1 := EvenWeightSubcode( BCHCode( 8, 4, GF(3) ) );
List( AsSSortedList( C1 ), WeightCodeword );
EvenWeightSubcode( ReedMullerCode( 1, 3 ) );
-->

<C>ExtendedCode</C> also returns a related code of only even weights, but
without reducing its dimension (see 
<Ref Func="ExtendedCode" Style="Number"/>).

<ManSection>
<Func Name="PermutedCode" Arg=" C L "/>

<Description>
<C>PermutedCode</C> returns <A>C</A> after column permutations. 
<A>L</A> (in GAP disjoint cycle notation)
is the permutation to be executed on the columns of <A>C</A>. 
If <A>C</A> is cyclic, the result in general is no 
longer cyclic. If a permutation results in the same code as 
<A>C</A>, this permutation belongs to the automorphism group of
<A>C</A> (see 
<Ref Func="AutomorphismGroup" Style="Number"/>). 
In  any case, the returned code is
equivalent to <A>C</A> 
(see <Ref Func="IsEquivalent" Style="Number"/>).
</Description>
</ManSection>

<Example>
gap> C1 := PuncturedCode( ReedMullerCode( 1, 4 ) );
a linear [15,5,7]5 punctured code
gap> C2 := BCHCode( 15, 7, GF(2) );
a cyclic [15,5,7]5 BCH code, delta=7, b=1 over GF(2)
gap> C2 = C1;
false
gap> p := CodeIsomorphism( C1, C2 );
( 2, 4,14, 9,13, 7,11,10, 6, 8,12, 5)
gap> C3 := PermutedCode( C1, p );
a linear [15,5,7]5 permuted code
gap> C2 = C3;
true 
</Example>
<!--
C1 := PuncturedCode( ReedMullerCode( 1, 4 ) );
C2 := BCHCode( 15, 7, GF(2) );
C2 = C1;
p := CodeIsomorphism( C1, C2 );
C3 := PermutedCode( C1, p );
C2 = C3;
-->

<ManSection>
<Func Name="ExpurgatedCode" Arg=" C L "/>

<Description>
<C>ExpurgatedCode</C> expurgates the code <A>C</A>> by throwing 
away codewords in list <A>L</A>. <A>C</A> must be a linear code. 
<A>L</A> must be a list of codeword input. 
The generator matrix of the new code no longer is a basis for the
codewords specified by <A>L</A>.  Since the returned code is 
still linear, it is very likely that, besides the words of 
<A>L</A>, more codewords of <A>C</A> are no longer in the 
new code.
</Description>
</ManSection>

<Example>
gap> C1 := HammingCode( 4 );; WeightDistribution( C1 );
[ 1, 0, 0, 35, 105, 168, 280, 435, 435, 280, 168, 105, 35, 0, 0, 1 ]
gap> L := Filtered( AsSSortedList(C1), i -> WeightCodeword(i) = 3 );;
gap> C2 := ExpurgatedCode( C1, L );
a linear [15,4,3..4]5..11 code, expurgated with 7 word(s)
gap> WeightDistribution( C2 );
[ 1, 0, 0, 0, 14, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 ] 
</Example>
<!--
C1 := HammingCode( 4 );; WeightDistribution( C1 );
L := Filtered( AsSSortedList(C1), i -> WeightCodeword(i) = 3 );;
C2 := ExpurgatedCode( C1, L );
WeightDistribution( C2 );
-->

This function does not work on non-linear codes.  
For removing words from a non-linear code, use
<C>RemovedElementsCode</C> (see
<Ref Func="RemovedElementsCode" Style="Number"/>).  
For  expurgating a code of all words of odd
weight, use `EvenWeightSubcode' (see 
<Ref Func="EvenWeightSubcode" Style="Number"/>).


<ManSection>
<Func Name="AugmentedCode" Arg=" C L "/>

<Description>
<C>AugmentedCode</C> returns <A>C</A> after augmenting. 
<A>C</A> must be a linear code, <A>L</A> must be a list of 
codeword inputs.  The generator matrix of the
new code is a basis for the codewords specified by <A>L</A> 
as well as the words that were already in code <A>C</A>. 
Note that the new code in general will consist of more 
words than only the codewords of <A>C</A> and the words
<A>L</A>. The returned code is also a linear code.
<P/>
This command can also be called with the syntax
<C>AugmentedCode(C)</C>.

When  called without a list of codewords, 
<C>AugmentedCode</C> returns <A>C</A>
after adding the all-ones vector to the generator matrix. 
<A>C</A> must be a linear code.   
If the all-ones vector was already in the code, nothing
happens and a copy of the argument is returned. If <A>C</A> 
is a binary code which does not contain the all-ones vector,   
the complement of all codewords is added.
</Description>
</ManSection>

<Example>
gap> C31 := ReedMullerCode( 1, 3 );
a linear [8,4,4]2 Reed-Muller (1,3) code over GF(2)
gap> C32 := AugmentedCode(C31,["00000011","00000101","00010001"]);
a linear [8,7,1..2]1 code, augmented with 3 word(s)
gap> C32 = ReedMullerCode( 2, 3 );
true 
gap> C1 := CordaroWagnerCode(6);
a linear [6,2,4]2..3 Cordaro-Wagner code over GF(2)
gap> Codeword( [0,0,1,1,1,1] ) in C1;
true
gap> C2 := AugmentedCode( C1 );
a linear [6,3,1..2]2..3 code, augmented with 1 word(s)
gap> Codeword( [1,1,0,0,0,0] ) in C2;
true
</Example>
<!--
C31 := ReedMullerCode( 1, 3 );
C32 := AugmentedCode(C31,["00000011","00000101","00010001"]);
C32 = ReedMullerCode( 2, 3 );
C1 := CordaroWagnerCode(6);
Codeword( [0,0,1,1,1,1] ) in C1;
C2 := AugmentedCode( C1 );
Codeword( [1,1,0,0,0,0] ) in C2;
-->

The function <C>AddedElementsCode</C> adds elements to the codewords instead
of adding them to the basis (see 
<Ref Func="AddedElementsCode" Style="Number"/>).

<ManSection>
<Func Name="RemovedElementsCode" Arg=" C L "/>

<Description>
<C>RemovedElementsCode</C> returns code <A>C</A> after removing 
a list of codewords <A>L</A> from its elements. <A>L</A> must be a 
list of codeword input.  The result is an unrestricted code.
</Description>
</ManSection>

<Example>
gap> C1 := HammingCode( 4 );; WeightDistribution( C1 );
[ 1, 0, 0, 35, 105, 168, 280, 435, 435, 280, 168, 105, 35, 0, 0, 1 ]
gap> L := Filtered( AsSSortedList(C1), i -> WeightCodeword(i) = 3 );;
gap> C2 := RemovedElementsCode( C1, L );
a (15,2013,3..15)2..15 code with 35 word(s) removed
gap> WeightDistribution( C2 );
[ 1, 0, 0, 0, 105, 168, 280, 435, 435, 280, 168, 105, 35, 0, 0, 1 ]
gap> MinimumDistance( C2 );
3        # C2 is not linear, so the minimum weight does not have to
         # be equal to the minimum distance 
</Example>
<!--
C1 := HammingCode( 4 );; WeightDistribution( C1 );
L := Filtered( AsSSortedList(C1), i -> WeightCodeword(i) = 3 );;
C2 := RemovedElementsCode( C1, L );
WeightDistribution( C2 );
MinimumDistance( C2 );
-->

Adding elements  to a  code is  done by  the function 
<C>AddedElementsCode</C>
(see 
<Ref Func="AddedElementsCode" Style="Number"/>). 
To remove codewords from the base of a linear
code, use <C>ExpurgatedCode</C> (see 
<Ref Func="ExpurgatedCode" Style="Number"/>).


<ManSection>
<Func Name="AddedElementsCode" Arg=" C L "/>

<Description>
<C>AddedElementsCode</C> returns code <A>C</A> after adding a 
list of codewords <A>L</A> to its elements. 
<A>L</A> must be a list of codeword  input. The result is an
unrestricted code.
</Description>
</ManSection>

<Example>
gap> C1 := NullCode( 6, GF(2) );
a cyclic [6,0,6]6 nullcode over GF(2)
gap> C2 := AddedElementsCode( C1, [ "111111" ] );
a (6,2,1..6)3 code with 1 word(s) added
gap> IsCyclicCode( C2 );
true
gap> C3 := AddedElementsCode( C2, [ "101010", "010101" ] );
a (6,4,1..6)2 code with 2 word(s) added
gap> IsCyclicCode( C3 );
true 
</Example>
<!--
C1 := NullCode( 6, GF(2) );
C2 := AddedElementsCode( C1, [ "111111" ] );
IsCyclicCode( C2 );
C3 := AddedElementsCode( C2, [ "101010", "010101" ] );
IsCyclicCode( C3 );
-->

To remove elements from a code, use <C>RemovedElementsCode</C>  (see
<Ref Func="RemovedElementsCode" Style="Number"/>). 
To add elements to the base of a linear code, use
<C>AugmentedCode</C> (see 
<Ref Func="AugmentedCode" Style="Number"/>).

<ManSection>
<Func Name="ShortenedCode" Arg=" C [L] "/>

<Description>
<C>ShortenedCode( C )</C> returns the code <A>C</A> shortened by 
taking a cross section.  If <A>C</A> is a linear code, this is done  
by removing all codewords that start with a non-zero entry, after which
the first column is cut off.  If <A>C</A>
was a <M>[n,k,d]</M> code, the shortened code generally is a 
<M>[n-1,k-1,d]</M> code. It is possible that the dimension 
remains the same; it is also possible that the minimum distance 
increases.
<P/>
If  <A>C</A> is a non-linear code, <C>ShortenedCode</C> first 
checks which finite
field element occurs most often in the first column of the codewords. The
codewords not starting with this element are removed from the code, after
which the first  column is cut off. The resulting shortened code has at
least the same minimum distance as <A>C</A>.
<P/>
This command can also be called using the syntax
<C>ShortenedCode(C,L)</C>.
When called in this format, <C>ShortenedCode</C> repeats the
shortening process on each of the columns specified by <A>L</A>. 
<A>L</A> therefore is a list of integers. The column numbers in 
<A>L</A>  are the numbers as they are before the shortening process. 
If <A>L</A> has <M>l</M> entries, the returned code has a word 
length of <M>l</M> positions shorter than <A>C</A>.
</Description>
</ManSection>

<Example>
gap> C1 := HammingCode( 4 );
a linear [15,11,3]1 Hamming (4,2) code over GF(2)
gap> C2 := ShortenedCode( C1 );
a linear [14,10,3]2 shortened code
gap> C3 := ElementsCode( ["1000", "1101", "0011" ], GF(2) );
a (4,3,1..4)2 user defined unrestricted code over GF(2)
gap> MinimumDistance( C3 );
2
gap> C4 := ShortenedCode( C3 );
a (3,2,2..3)1..2 shortened code
gap> AsSSortedList( C4 );
[ [ 0 0 0 ], [ 1 0 1 ] ]
gap> C5 := HammingCode( 5, GF(2) );
a linear [31,26,3]1 Hamming (5,2) code over GF(2)
gap> C6 := ShortenedCode( C5, [ 1, 2, 3 ] );
a linear [28,23,3]2 shortened code
gap> OptimalityLinearCode( C6 );
0
</Example>
<!--
C1 := HammingCode( 4 );
C2 := ShortenedCode( C1 );
C3 := ElementsCode( ["1000", "1101", "0011" ], GF(2) );
MinimumDistance( C3 );
C4 := ShortenedCode( C3 );
AsSSortedList( C4 );
C5 := HammingCode( 5, GF(2) );
C6 := ShortenedCode( C5, [ 1, 2, 3 ] );
OptimalityLinearCode( C6 );
-->

The function <C>LengthenedCode</C> lengthens the code again (only for linear
codes), see 
<Ref Func="LengthenedCode" Style="Number"/>. 
In general, this is not exactly the inverse function.

<ManSection>
<Func Name="LengthenedCode" Arg=" C [i] "/>

<Description>
<C>LengthenedCode( C )</C> returns the code <A>C</A> lengthened.  
<A>C</A>  must be a linear code. First, the all-ones vector is 
added to the generator matrix (see
<Ref Func="AugmentedCode" Style="Number"/>). 
If the all-ones vector was already a codeword, nothing
happens to the code.  Then, the code is extended <A>i</A> times  (see
<Ref Func="ExtendedCode" Style="Number"/>). <A>i</A> is equal to 
<M>1</M> by default. If <A>C</A> was an <M>[n,k]</M>
code, the new code generally is a <M>[n+i,k+1]</M> code.
</Description>
</ManSection>

<Example>
gap> C1 := CordaroWagnerCode( 5 );
a linear [5,2,3]2 Cordaro-Wagner code over GF(2)
gap> C2 := LengthenedCode( C1 );
a linear [6,3,2]2..3 code, lengthened with 1 column(s) 
</Example>
<!--
C1 := CordaroWagnerCode( 5 );
C2 := LengthenedCode( C1 );
-->

<C>ShortenedCode</C>' shortens the code, see 
<Ref Func="ShortenedCode" Style="Number"/>. In general, this
is not exactly the inverse function.

<ManSection>
	<Func Name="SubCode" Arg=" C [s] "/>

	<Description>
		This function <C>SubCode</C> returns a subcode of
		<A>C</A> by taking the first <M>k - s</M> rows of
		the generator matrix of <A>C</A>, where <M>k</M>
		is the dimension of <A>C</A>. The interger <A>s</A>
		may be omitted and in this case it is assumed as 1.
	</Description>
</ManSection>

<Example>
gap> C := BCHCode(31,11);
a cyclic [31,11,11]7..11 BCH code, delta=11, b=1 over GF(2)
gap> S1:= SubCode(C);
a linear [31,10,11]7..13 subcode
gap> WeightDistribution(S1);
[ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 120, 190, 0, 0, 272, 255, 0, 0, 120, 66,
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
gap> S2:= SubCode(C, 8);
a linear [31,3,11]14..20 subcode
gap> History(S2);
[ "a linear [31,3,11]14..20 subcode of",
  "a cyclic [31,11,11]7..11 BCH code, delta=11, b=1 over GF(2)" ]
gap> WeightDistribution(S2);
[ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0,
  0, 0, 0, 0, 0, 0, 0 ]
</Example>

<!--
C := BCHCode(31,11);
S1:= SubCode(C);
WeightDistribution(S1);
S2:= SubCode(C, 8);
History(S2);
WeightDistribution(S2);
-->

<ManSection>
<Func Name="ResidueCode" Arg=" C [c] "/>

<Description>
The function <C>ResidueCode</C> takes a codeword <A>c</A>
of <A>C</A> (if <A>c</A> is omitted, a 
codeword of minimal weight is used). 
It removes this word and all its linear combinations from 
the code and then  punctures the code in the coordinates 
where <A>c</A> is unequal to zero. The resulting code is an
<M>[n-w, k-1, d-\lfloor w*(q-1)/q \rfloor ]</M> code.
<A>C</A> must be a
linear code and <A>c</A> must be non-zero.
If <A>c</A> is not in <A></A> then no change is made to <A>C</A>.
</Description>
</ManSection>

<Example>
gap> C1 := BCHCode( 15, 7 );
a cyclic [15,5,7]5 BCH code, delta=7, b=1 over GF(2)
gap> C2 := ResidueCode( C1 );
a linear [8,4,4]2 residue code
gap> c := Codeword( [ 0,0,0,1,0,0,1,1,0,1,0,1,1,1,1 ], C1);;
gap> C3 := ResidueCode( C1, c );
a linear [7,4,3]1 residue code 
</Example>
<!--
C1 := BCHCode( 15, 7 );
C2 := ResidueCode( C1 );
c := Codeword( [ 0,0,0,1,0,0,1,1,0,1,0,1,1,1,1 ], C1);;
C3 := ResidueCode( C1, c );
-->

<ManSection>
<Func Name="ConstructionBCode" Arg=" C "/>

<Description>
The function <C>ConstructionBCode</C> takes a binary linear code
<A>C</A> and calculates the minimum distance of the dual of 
<A>C</A> (see 
<Ref Func="DualCode" Style="Number"/>). It
then removes the columns of the parity check matrix of 
<A>C</A>  where a codeword of the dual code of minimal weight
has coordinates unequal to zero. 
The resulting matrix is a parity check matrix for an 
<M>[n-dd, k-dd+1, \geq d]</M> code, where <M>dd</M> is the 
minimum distance  of the dual of <A>C</A>.
</Description>
</ManSection>

<Example>
gap> C1 := ReedMullerCode( 2, 5 );
a linear [32,16,8]6 Reed-Muller (2,5) code over GF(2)
gap> C2 := ConstructionBCode( C1 );
a linear [24,9,8]5..10 Construction B (8 coordinates)
gap> BoundsMinimumDistance( 24, 9, GF(2) );
rec( n := 24, k := 9, q := 2, references := rec(  ), 
  construction := [ [ Operation "UUVCode" ], 
      [ [ [ Operation "UUVCode" ], [ [ [ Operation "DualCode" ], 
                      [ [ [ Operation "RepetitionCode" ], [ 6, 2 ] ] ] ], 
                  [ [ Operation "CordaroWagnerCode" ], [ 6 ] ] ] ], 
          [ [ Operation "CordaroWagnerCode" ], [ 12 ] ] ] ], lowerBound := 8, 
  lowerBoundExplanation := [ "Lb(24,9)=8, u u+v construction of C1 and C2:", 
      "Lb(12,7)=4, u u+v construction of C1 and C2:", 
      "Lb(6,5)=2, dual of the repetition code", 
      "Lb(6,2)=4, Cordaro-Wagner code", "Lb(12,2)=8, Cordaro-Wagner code" ], 
  upperBound := 8, 
  upperBoundExplanation := [ "Ub(24,9)=8, otherwise construction B would 
                             contradict:", "Ub(18,4)=8, Griesmer bound" ] )
# so C2 is optimal
</Example>
<!--
C1 := ReedMullerCode( 2, 5 );
C2 := ConstructionBCode( C1 );
BoundsMinimumDistance( 24, 9, GF(2) );
-->


<ManSection>
<Func Name="DualCode" Arg=" C "/>

<Description>
<C>DualCode</C> returns the dual code of <A>C</A>. 
The dual code consists of all codewords that are orthogonal to the 
codewords of <A>C</A>. If <A>C</A> is a linear code with generator 
matrix <M>G</M>, the dual code has parity check matrix <M>G</M>
(or if <A>C</A> has parity check matrix <M>H</M>,  the 
dual code has generator matrix <M>H</M>). So if <A>C</A> 
is a linear <M>[n, k]</M> code, the dual code of <A>C</A> is a
linear <M>[n,  n-k]</M> code. If <A>C</A> is a cyclic code 
with generator polynomial <M>g(x)</M>, the dual code has the 
reciprocal polynomial of <M>g(x)</M> as check polynomial.
<P/>
The dual code is always a linear code, even if <A>C</A> is non-linear.
<P/>
If a code <A>C</A> is equal to its dual code, it is called 
<E>self-dual</E>.
</Description>
</ManSection>

<Example>
gap> R := ReedMullerCode( 1, 3 );
a linear [8,4,4]2 Reed-Muller (1,3) code over GF(2)
gap> RD := DualCode( R );
a linear [8,4,4]2 Reed-Muller (1,3) code over GF(2)
gap> R = RD;
true
gap> N := WholeSpaceCode( 7, GF(4) );
a cyclic [7,7,1]0 whole space code over GF(4)
gap> DualCode( N ) = NullCode( 7, GF(4) );
true 
</Example>
<!--
R := ReedMullerCode( 1, 3 );
RD := DualCode( R );
R = RD;
N := WholeSpaceCode( 7, GF(4) );
DualCode( N ) = NullCode( 7, GF(4) );
-->

<Index>
self-dual
</Index>

<ManSection>
<Func Name="ConversionFieldCode" Arg=" C "/>

<Description>
<C>ConversionFieldCode</C> returns the code obtained from
<A>C</A> after converting its field. 
If the field of <A>C</A> is <M>GF(q^m)</M>, 
the returned code has field <M>GF(q)</M>. Each
symbol of every codeword is replaced by a concatenation of <M>m</M> symbols
from <M>GF(q)</M>. If <A>C</A> is an <M>(n, M, d_1)</M> code, 
the returned code is a <M>(n\cdot m, M, d_2)</M> code, 
where <M>d_2 > d_1</M>.
<P/>
See also <Ref Func="HorizontalConversionFieldMat" Style="Number"/>.
</Description>
</ManSection>

<Example>
gap> R := RepetitionCode( 4, GF(4) );
a cyclic [4,1,4]3 repetition code over GF(4)
gap> R2 := ConversionFieldCode( R );
a linear [8,2,4]3..4 code, converted to basefield GF(2)
gap> Size( R ) = Size( R2 );
true
gap> GeneratorMat( R );
[ [ Z(2)^0, Z(2)^0, Z(2)^0, Z(2)^0 ] ]
gap> GeneratorMat( R2 );
[ [ Z(2)^0, 0*Z(2), Z(2)^0, 0*Z(2), Z(2)^0, 0*Z(2), Z(2)^0, 0*Z(2) ],
  [ 0*Z(2), Z(2)^0, 0*Z(2), Z(2)^0, 0*Z(2), Z(2)^0, 0*Z(2), Z(2)^0 ] ] 
</Example>
<!--
R := RepetitionCode( 4, GF(4) );
R2 := ConversionFieldCode( R );
Size( R ) = Size( R2 );
GeneratorMat( R );
GeneratorMat( R2 );
-->

<ManSection>
<Func Name="TraceCode" Arg=" C "/>

<Description>
Input: <A>C</A> is a linear code defined over an extension <M>E</M> of <A>F</A>
(<A>F</A> is the ``base field'')
<P/>
Output: The linear code generated by <M>Tr_{E/F}(c)</M>, for all <M>c \in C</M>.
<P/>
<C>TraceCode</C> returns the image of the code <A>C</A> under the
trace map. If the field of <A>C</A> is <M>GF(q^m)</M>, 
the returned code has field <M>GF(q)</M>. 
<P/>
Very slow. It does not seem to be easy to related the parameters of the
trace code to the original except in the ``Galois closed'' case.
</Description>
</ManSection>

<Example>
gap> C:=RandomLinearCode(10,4,GF(4)); MinimumDistance(C);
a  [10,4,?] randomly generated code over GF(4)
5
gap> trC:=TraceCode(C,GF(2)); MinimumDistance(trC);
a linear [10,7,1]1..3 user defined unrestricted code over GF(2)
1

</Example>
<!--
C:=RandomLinearCode(10,4,GF(4)); MinimumDistance(C);
trC:=TraceCode(C,GF(2)); MinimumDistance(trC);

-->

<ManSection>
<Func Name="CosetCode" Arg=" C w "/>

<Description>
<C>CosetCode</C> returns the coset of a code 
<A>C</A> with respect to word <A>w</A>.
<A>w</A> must be of the codeword type. Then, <A>w</A> is 
added to each codeword of <A>C</A>, yielding the elements of
the new code. If <A>C</A> is linear and <A>w</A> is
an element of <A>C</A>, the new code is equal to <A>C</A>, 
otherwise the new code is an unrestricted code.
<P/>
Generating a coset is also possible by simply adding the word 
<A>w</A> to <A>C</A>. See 
<Ref Label="Operations for Codes" Style="Number"/>.
</Description>
</ManSection>

<Example>
gap> H := HammingCode(3, GF(2));
a linear [7,4,3]1 Hamming (3,2) code over GF(2)
gap> c := Codeword("1011011");; c in H;
false
gap> C := CosetCode(H, c);
a (7,16,3)1 coset code
gap> List(AsSSortedList(C), el-> Syndrome(H, el));
[ [ 1 1 1 ], [ 1 1 1 ], [ 1 1 1 ], [ 1 1 1 ], [ 1 1 1 ], [ 1 1 1 ],
  [ 1 1 1 ], [ 1 1 1 ], [ 1 1 1 ], [ 1 1 1 ], [ 1 1 1 ], [ 1 1 1 ],
  [ 1 1 1 ], [ 1 1 1 ], [ 1 1 1 ], [ 1 1 1 ] ]
# All elements of the coset have the same syndrome in H 
</Example>
<!--
H := HammingCode(3, GF(2));
c := Codeword("1011011");; c in H;
C := CosetCode(H, c);
List(AsSSortedList(C), el-> Syndrome(H, el));
-->

<ManSection>
<Func Name="ConstantWeightSubcode" Arg=" C w "/>

<Description>
<C>ConstantWeightSubcode</C> returns the subcode of 
<A>C</A> that only has codewords of weight <A>w</A>. 
The resulting code is a non-linear code, because
it does not contain the all-zero vector.
<P/>
This command also can be called with the syntax
<C>ConstantWeightSubcode(C)</C>
In this format, <C>ConstantWeightSubcode</C> returns 
the subcode of <A>C</A> consisting of all minimum weight 
codewords of <A>C</A>.
<P/>
<C>ConstantWeightSubcode</C> first checks if Leon's binary 
<C>wtdist</C> exists on your computer (in the default directory).
If it does, then this program is called. Otherwise, 
the constant weight subcode is computed using a GAP program
which checks each codeword in <A>C</A> to see if it is of the
desired weight. 

</Description>
</ManSection>

<Example>
gap> N := NordstromRobinsonCode();; WeightDistribution(N);
[ 1, 0, 0, 0, 0, 0, 112, 0, 30, 0, 112, 0, 0, 0, 0, 0, 1 ]
gap> C := ConstantWeightSubcode(N, 8);
a (16,30,6..16)5..8 code with codewords of weight 8
gap> WeightDistribution(C);
[ 0, 0, 0, 0, 0, 0, 0, 0, 30, 0, 0, 0, 0, 0, 0, 0, 0 ] 
gap> eg := ExtendedTernaryGolayCode();; WeightDistribution(eg);
[ 1, 0, 0, 0, 0, 0, 264, 0, 0, 440, 0, 0, 24 ]
gap> C := ConstantWeightSubcode(eg);
a (12,264,6..12)3..6 code with codewords of weight 6
gap> WeightDistribution(C);
[ 0, 0, 0, 0, 0, 0, 264, 0, 0, 0, 0, 0, 0 ] 
</Example>
<!--
N := NordstromRobinsonCode();; WeightDistribution(N);
C := ConstantWeightSubcode(N, 8);
WeightDistribution(C);
eg := ExtendedTernaryGolayCode();; WeightDistribution(eg);
C := ConstantWeightSubcode(eg);
WeightDistribution(C);
-->


<ManSection>
<Func Name="StandardFormCode" Arg=" C "/>

<Description>
<C>StandardFormCode</C> returns <A>C</A> after putting it
in standard form. If <A>C</A> is a non-linear  code, this means the 
elements are organized using lexicographical order. This means they 
form a legal GAP `Set'.
<P/>
If <A>C</A> is a linear code, the generator matrix and parity check matrix are
put in standard form. The generator matrix then has an identity matrix in
its left part, the parity check matrix has an identity matrix in its
right  part. Although <Package>GUAVA</Package> always puts both 
matrices in a standard form using <C>BaseMat</C>, this never 
alters the code. <C>StandardFormCode</C> even
applies column permutations if unavoidable, and thereby changes the
code. The column permutations are recorded in the construction history of
the  new  code (see <Ref Func="Display" Style="Number"/>).  
<A>C</A> and the new code are of course equivalent.
<P/>
If <A>C</A> is a cyclic code, its generator matrix cannot be 
put in the usual upper triangular form, because then it would be 
inconsistent with the generator polynomial. The reason is that 
generating the elements from the generator matrix  would result in a 
different order than  generating the elements from the generator 
polynomial.  This is an unwanted effect, and therefore 
<C>StandardFormCode</C> just returns a copy of <A>C</A> 
for cyclic codes.
</Description>
</ManSection>

<Example>
gap> G := GeneratorMatCode( Z(2) * [ [0,1,1,0], [0,1,0,1], [0,0,1,1] ], 
          "random form code", GF(2) );
a linear [4,2,1..2]1..2 random form code over GF(2)
gap> Codeword( GeneratorMat( G ) );
[ [ 0 1 0 1 ], [ 0 0 1 1 ] ]
gap> Codeword( GeneratorMat( StandardFormCode( G ) ) );
[ [ 1 0 0 1 ], [ 0 1 0 1 ] ] 
</Example>
<!--
G := GeneratorMatCode( Z(2) * [ [0,1,1,0], [0,1,0,1], [0,0,1,1] ], "random form code", GF(2) );
Codeword( GeneratorMat( G ) );
Codeword( GeneratorMat( StandardFormCode( G ) ) );
-->

<ManSection>
<Func Name="PiecewiseConstantCode" Arg=" part wts [F] "/>

<Description>
<C>PiecewiseConstantCode</C> returns a code with length 
<M>n = \sum n_i</M>, where
<A>part</A>=<M>[ n_1, \dots, n_k ]</M>. <A>wts</A> is a list of 
<A>constraints</A> <M>w=(w_1,...,w_k)</M>, each of length <M>k</M>,
where <M>0 \leq w_i \leq n_i</M>. 
The default field is <M>GF(2)</M>.
<P/>
A constraint is a list of integers, and
a word <M>c = ( c_1, \dots, c_k )</M> 
(according to <A>part</A>, i.e., each <M>c_i</M> is a subword
of length <M>n_i</M>)
is in the resulting code if and only if,
for some constraint <M>w \in</M> <A>wts</A>,
<M>\|c_i\| = w_i</M> for all <M>1 \leq i \leq k</M>,
where <M>\| ...\|</M> denotes the Hamming weight.
<P/>
An example might make things clearer:
</Description>
</ManSection>

<Example>
gap> PiecewiseConstantCode( [ 2, 3 ],
     [ [ 0, 0 ], [ 0, 3 ], [ 1, 0 ], [ 2, 2 ] ],GF(2) );
the C code programs are compiled, so using Leon's binary....
the C code programs are compiled, so using Leon's binary....
the C code programs are compiled, so using Leon's binary....
the C code programs are compiled, so using Leon's binary....
a (5,7,1..5)1..5 piecewise constant code over GF(2)
gap> AsSSortedList(last);
[ [ 0 0 0 0 0 ], [ 0 0 1 1 1 ], [ 0 1 0 0 0 ], [ 1 0 0 0 0 ], 
  [ 1 1 0 1 1 ], [ 1 1 1 0 1 ], [ 1 1 1 1 0 ] ]
gap>

</Example>
<!--
PiecewiseConstantCode( [ 2, 3 ],[ [ 0, 0 ], [ 0, 3 ], [ 1, 0 ], [ 2, 2 ] ],GF(2) );
AsSSortedList(last);
-->

The first constraint is satisfied by codeword 1,
the second by codeword 2,
the third by codewords 3 and 4,
and the fourth by codewords 5, 6 and 7.


</Section>

<Section>
<Heading>
Functions that Generate a New Code from Two or More Given Codes
</Heading>
<Label Name="Functions that Generate a New Code from Two or More Given Codes"/>


<ManSection>
<Func Name="DirectSumCode" Arg=" C1 C2 "/>

<Description>
<C>DirectSumCode</C> returns the direct sum of codes 
<A>C1</A> and <A>C2</A>. The direct sum code consists of every 
codeword of <A>C1</A> concatenated by every codeword of <A>C2</A>. 
Therefore, if <A>Ci</A> was a <M>(n_i,M_i,d_i)</M>
code, the result is a <M>(n_1+n_2,M_1*M_2,min(d_1,d_2))</M> code.
<P/>
If both <A>C1</A> and <A>C2</A> are linear codes, the result 
is also a linear code. If one of them is non-linear, the direct 
sum is non-linear too. In general, a direct sum code is not cyclic.
<P/>
Performing  a direct sum can also be done by adding two codes (see
Section <Ref Label="Operations for Codes" Style="Number"/>). 
Another often used method is the `u, u+v'-construction, 
described in <Ref Func="UUVCode" Style="Number"/>.
</Description>
</ManSection>

<Example>
gap> C1 := ElementsCode( [ [1,0], [4,5] ], GF(7) );;
gap> C2 := ElementsCode( [ [0,0,0], [3,3,3] ], GF(7) );;
gap> D := DirectSumCode(C1, C2);;
gap> AsSSortedList(D);
[ [ 1 0 0 0 0 ], [ 1 0 3 3 3 ], [ 4 5 0 0 0 ], [ 4 5 3 3 3 ] ]
gap> D = C1 + C2;   # addition = direct sum
true 
</Example>
<!--
C1 := ElementsCode( [ [1,0], [4,5] ], GF(7) );;
C2 := ElementsCode( [ [0,0,0], [3,3,3] ], GF(7) );;
D := DirectSumCode(C1, C2);;
AsSSortedList(D);
D = C1 + C2;   # addition = direct sum
-->

<ManSection>
<Func Name="UUVCode" Arg=" C1 C2 "/>

<Description>
<C>UUVCode</C> returns the so-called <M>(u\|u+v)</M> construction 
applied to <A>C1</A> and <A>C2</A>. 
The resulting code consists of every codeword <M>u</M> of
<A>C1</A> concatenated by the sum of <M>u</M> and every codeword 
<M>v</M> of <A>C2</A>.  If <A>C1</A> and <A>C2</A> have different 
word lengths, sufficient zeros are added to the shorter code to 
make this sum possible. If <A>Ci</A> is a <M>(n_i,M_i,d_i)</M> 
code,  the  result is an 
<M>(n_1+max(n_1,n_2),M_1\cdot M_2,min(2\cdot d_1,d_2))</M> code.
<P/>
If both <A>C1</A> and <A>C2</A> are linear codes, the result is also a linear
code. If one  of them is non-linear, the UUV sum is non-linear too.
In general, a UUV sum code is not cyclic.
<P/>
The function <C>DirectSumCode</C> returns another sum of codes (see
<Ref Func="DirectSumCode" Style="Number"/>).
</Description>
</ManSection>

<Example>
gap> C1 := EvenWeightSubcode(WholeSpaceCode(4, GF(2)));
a cyclic [4,3,2]1 even weight subcode
gap> C2 := RepetitionCode(4, GF(2));
a cyclic [4,1,4]2 repetition code over GF(2)
gap> R := UUVCode(C1, C2);
a linear [8,4,4]2 U U+V construction code
gap> R = ReedMullerCode(1,3);
true 
</Example>
<!--
C1 := EvenWeightSubcode(WholeSpaceCode(4, GF(2)));
C2 := RepetitionCode(4, GF(2));
R := UUVCode(C1, C2);
R = ReedMullerCode(1,3);

-->


<ManSection>
<Func Name="DirectProductCode" Arg=" C1 C2 "/>

<Description>
<C>DirectProductCode</C> returns the direct product of codes 
<A>C1</A> and <A>C2</A>. Both must be linear codes.  
Suppose <A>Ci</A> has generator matrix <M>G_i</M>. 
The direct product of <A>C1</A> and <A>C2</A> 
then has the Kronecker product of <M>G_1</M>  
and <M>G_2</M>  as the generator matrix (see
the GAP command <C>KroneckerProduct</C>).
<P/>
If <A>Ci</A> is a <M>[n_i, k_i, d_i]</M> code, 
the direct product then is an 
<M>[n_1\cdot n_2,k_1\cdot k_2,d_1\cdot d_2]</M> code.
</Description>
</ManSection>

<Example>
gap> L1 := LexiCode(10, 4, GF(2));
a linear [10,5,4]2..4 lexicode over GF(2)
gap> L2 := LexiCode(8, 3, GF(2));
a linear [8,4,3]2..3 lexicode over GF(2)
gap> D := DirectProductCode(L1, L2);
a linear [80,20,12]20..45 direct product code 
</Example>
<!--
L1 := LexiCode(10, 4, GF(2));
L2 := LexiCode(8, 3, GF(2));
D := DirectProductCode(L1, L2);
-->

<ManSection>
<Func Name="IntersectionCode" Arg=" C1 C2 "/>

<Description>
<C>IntersectionCode</C> returns the intersection of 
codes <A>C1</A> and <A>C2</A>.
This code consists of all codewords that are both in 
<A>C1</A> and <A>C2</A>.
If both codes are linear, the result is also linear. 
If both are cyclic, the result is also cyclic.

</Description>
</ManSection>

<Example>
gap> C := CyclicCodes(7, GF(2));
[ a cyclic [7,7,1]0 enumerated code over GF(2),
  a cyclic [7,6,1..2]1 enumerated code over GF(2),
  a cyclic [7,3,1..4]2..3 enumerated code over GF(2),
  a cyclic [7,0,7]7 enumerated code over GF(2),
  a cyclic [7,3,1..4]2..3 enumerated code over GF(2),
  a cyclic [7,4,1..3]1 enumerated code over GF(2),
  a cyclic [7,1,7]3 enumerated code over GF(2),
  a cyclic [7,4,1..3]1 enumerated code over GF(2) ]
gap> IntersectionCode(C[6], C[8]) = C[7];
true 
</Example>

<Index>hull</Index> 
The <E>hull</E> of a linear code is the
intersection of the code with its dual code. In other words,
the hull of <M>C</M> is
<C>IntersectionCode(C, DualCode(C))</C>.

<ManSection>
<Func Name="UnionCode" Arg=" C1 C2 "/>

<Description>
<C>UnionCode</C> returns the union of codes 
<A>C1</A> and <A>C2</A>. This code consists of the union of 
all codewords of <A>C1</A> and <A>C2</A> and all
linear combinations. Therefore this function works only for linear
codes. The function <C>AddedElementsCode</C> can be used for non-linear codes,
or if  the  resulting code should not include linear combinations.  See
<Ref Func="AddedElementsCode" Style="Number"/>.  
If both arguments  are  cyclic, the result  is also
cyclic.
</Description>
</ManSection>

<Example>
gap> G := GeneratorMatCode([[1,0,1],[0,1,1]]*Z(2)^0, GF(2));
a linear [3,2,1..2]1 code defined by generator matrix over GF(2)
gap> H := GeneratorMatCode([[1,1,1]]*Z(2)^0, GF(2));
a linear [3,1,3]1 code defined by generator matrix over GF(2)
gap> U := UnionCode(G, H);
a linear [3,3,1]0 union code
gap> c := Codeword("010");; c in G;
false
gap> c in H;
false
gap> c in U;
true 
</Example>
<!--
G := GeneratorMatCode([[1,0,1],[0,1,1]]*Z(2)^0, GF(2));
H := GeneratorMatCode([[1,1,1]]*Z(2)^0, GF(2));
U := UnionCode(G, H);
c := Codeword("010");; c in G;
c in H;
c in U;
-->


<ManSection>
<Func Name="ExtendedDirectSumCode" Arg=" L B m "/>

<Description>
The extended direct sum construction is described in section V of Graham
and Sloane <Cite Key="GS85"/>. 
The resulting code consists of <A>m</A> copies of <A>L</A>, extended by
repeating the codewords of <A>B</A> <A>m</A> times.
<P/>
Suppose <A>L</A> is an <M>[n_L, k_L]r_L</M> code, and <A>B</A>
is an <M>[n_L,  k_B]r_B</M> code (non-linear codes are also permitted). 
The length  of <A>B</A> must be equal to the length of 
<A>L</A>. The length of the new code is <M>n  =  m  n_L</M>,
the dimension (in the case of linear codes) is 
<M>k \leq m k_L + k_B</M>, and
the covering radius is <M>r \leq \lfloor m \Psi( L, B ) \rfloor</M>, 
with

<Display>
\Psi( L, B ) = \max_{u \in F_2^{n_L}} \frac{1}{2^{k_B}}
               \sum_{v \in B} {\rm d}( L, v + u ).
</Display>
However, this computation will not be executed, because it may be too
time consuming for large codes.
<P/>
If <M>L \subseteq B</M>, and <M>L</M> and <M>B</M> are linear codes, 
the last copy of <A>L</A> is omitted. In this case the 
dimension is <M>k = m k_L + (k_B  -  k_L)</M>.
</Description>
</ManSection>

<Example>
gap> c := HammingCode( 3, GF(2) );
a linear [7,4,3]1 Hamming (3,2) code over GF(2)
gap> d := WholeSpaceCode( 7, GF(2) );
a cyclic [7,7,1]0 whole space code over GF(2)
gap> e := ExtendedDirectSumCode( c, d, 3 );
a linear [21,15,1..3]2 3-fold extended direct sum code
</Example>
<!--
c := HammingCode( 3, GF(2) );
d := WholeSpaceCode( 7, GF(2) );
e := ExtendedDirectSumCode( c, d, 3 );
-->


<ManSection>
<Func Name="AmalgamatedDirectSumCode" Arg=" c1 c2 [check] "/>

<Description>
<C>AmalgamatedDirectSumCode</C> returns the amalgamated direct 
sum of the codes <A>c1</A> and <A>c2</A>. The amalgamated direct
sum code consists of all codewords of the form
<M>(u \, \| \,0 \, \| \, v)</M>
if
<M>(u \, \| \, 0) \in c_1</M>
and
<M>(0 \, \| \, v) \in c_2</M>
and all codewords of the form
<M>(u \, \| \, 1 \, \| \, v)</M>
if
<M>(u \, \| \, 1) \in c_1</M>
and
<M>(1 \, \| \, v) \in c_2</M>.
The result is a code with length
<M> n = n_1 + n_2 - 1 </M>
and size
<M> M \leq M_1 \cdot M_2 / 2 </M>.
<P/>
If both codes are linear, they will first be standardized, with
information symbols in the last and first coordinates of the first and
second code, respectively.
<P/>
If <A>c1</A> is a normal code (see 
<Ref Func="IsNormalCode" Style="Number"/>)
with the last coordinate acceptable
(see 
<Ref Func="IsCoordinateAcceptable" Style="Number"/>), 
and <A>c2</A>
is a normal code with the first coordinate acceptable, then the  covering
radius of the new code is <M>r \leq r_1 + r_2 </M>. However, checking whether
a code is normal or not is a lot of work, and almost all codes seem to be
normal. Therefore, an option <A>check</A> can be supplied. 
If <A>check</A> is true,
then the codes will be checked for normality.  
If <A>check</A> is false or omitted, then the codes will 
not be checked. In this case it is assumed
that they are normal. Acceptability of the last and first coordinate of
the first and second code, respectively, is in the last case also assumed
to be done by the user.
</Description>
</ManSection>

<Example>
gap> c := HammingCode( 3, GF(2) );
a linear [7,4,3]1 Hamming (3,2) code over GF(2)
gap> d := ReedMullerCode( 1, 4 );
a linear [16,5,8]6 Reed-Muller (1,4) code over GF(2)
gap> e := DirectSumCode( c, d );
a linear [23,9,3]7 direct sum code
gap> f := AmalgamatedDirectSumCode( c, d );;
gap> MinimumDistance( f );;
gap> CoveringRadius( f );; 
gap> f;
a linear [22,8,3]7 amalgamated direct sum code
</Example>
<!--
c := HammingCode( 3, GF(2) );
d := ReedMullerCode( 1, 4 );
e := DirectSumCode( c, d );
f := AmalgamatedDirectSumCode( c, d );;
MinimumDistance( f );;
CoveringRadius( f );; # takes some time
f;
-->

<ManSection>
<Func Name="BlockwiseDirectSumCode" Arg=" C1 L1 C2 L2 "/>

<Description>
<C>BlockwiseDirectSumCode</C> returns a subcode of the direct sum 
of <A>C1</A> and <A>C2</A>. The fields of <A>C1</A> and 
<A>C2</A> must be same.  The lists <A>L1</A> and <A>L2</A> 
are two equally long with elements from the ambient vector spaces
of <A>C1</A> and <A>C2</A>,  respectively, <E>or</E>
<A>L1</A> and <A>L2</A> are two equally long lists containing codes.  
The union of the codes in <A>L1</A> and <A>L2</A> must be 
<A>C1</A> and <A>C2</A>, respectively.
<P/>
In the first case, the blockwise direct sum code is defined as

<Display>
bds = \bigcup_{1 \leq i \leq \ell} ( C_1 + (L_1)_i ) \oplus ( C_2 + (L_2)_i ),
</Display>
where <M>\ell</M> is the length of <A>L1</A> and <A>L2</A>, 
and <M>\oplus</M> is the direct sum.
<P/>
In the second case, it is defined as

<Display>
bds = \bigcup_{1 \leq i \leq \ell} ( (L_1)_i \oplus (L_2)_i ).
</Display>
The length of the new code is <M>n = n_1 + n_2</M>.
</Description>
</ManSection>

<Example>
gap> C1 := HammingCode( 3, GF(2) );;
gap> C2 := EvenWeightSubcode( WholeSpaceCode( 6, GF(2) ) );;
gap> BlockwiseDirectSumCode( C1, [[ 0,0,0,0,0,0,0 ],[ 1,0,1,0,1,0,0 ]],
> C2, [[ 0,0,0,0,0,0 ],[ 1,0,1,0,1,0 ]] );
a (13,1024,1..13)1..2 blockwise direct sum code
</Example>
<!--
C1 := HammingCode( 3, GF(2) );;
C2 := EvenWeightSubcode( WholeSpaceCode( 6, GF(2) ) );;
BlockwiseDirectSumCode( C1, [[ 0,0,0,0,0,0,0 ],[ 1,0,1,0,1,0,0 ]], C2, [[ 0,0,0,0,0,0 ],[ 1,0,1,0,1,0 ]] );
-->


<ManSection>
	<Func Name="ConstructionXCode" Arg=" C A "/>

	<Description>
		Consider a list of <M>j</M> linear codes of the same length <M>N</M> over the same field <M>F</M>,
		<M>C = \{ C_1, C_2, \ldots, C_j \}</M>, where the parameter of the <M>i</M>th code is
		<M>C_i = [N, K_i, D_i]</M> and <M>C_j \subset C_{j-1} \subset \ldots \subset C_2 \subset C_1</M>.
		Consider a list of <M>j-1</M> auxiliary linear codes of the same field <M>F</M>,
		<M>A = \{ A_1, A_2, \ldots, A_{j-1} \}</M> where the parameter of the <M>i</M>th code <M>A_i</M>
		is <M>[n_i, k_i=(K_i-K_{i+1}), d_i]</M>, an <M>[n, K_1, d]</M> linear code over field <M>F</M>
		can be constructed where <M>n = N + \sum_{i=1}^{j-1} n_i</M>,
		and <M>d = \min\{ D_j, D_{j-1} + d_{j-1}, D_{j-2} + d_{j-2} + d_{j-1}, \ldots,
		D_1 + \sum_{i=1}^{j-1} d_i\}</M>.
		<P/>
		For more information on Construction X, refer to <Cite Key="Sloane72"/>.
	</Description>
</ManSection>

<Example>
gap> C1 := BCHCode(127, 43);
a cyclic [127,29,43]31..59 BCH code, delta=43, b=1 over GF(2)
gap> C2 := BCHCode(127, 47);
a cyclic [127,22,47..51]36..63 BCH code, delta=47, b=1 over GF(2)
gap> C3 := BCHCode(127, 55);
a cyclic [127,15,55]41..62 BCH code, delta=55, b=1 over GF(2)
gap> G1 := ShallowCopy( GeneratorMat(C2) );;
gap> Append(G1, [ GeneratorMat(C1)[23] ]);;
gap> C1 := GeneratorMatCode(G1, GF(2));
a linear [127,23,1..43]35..63 code defined by generator matrix over GF(2)
gap> MinimumDistance(C1);
43
gap> C := [ C1, C2, C3 ];
[ a linear [127,23,43]35..63 code defined by generator matrix over GF(2), 
  a cyclic [127,22,47..51]36..63 BCH code, delta=47, b=1 over GF(2), 
  a cyclic [127,15,55]41..62 BCH code, delta=55, b=1 over GF(2) ]
gap> IsSubset(C[1], C[2]);
true
gap> IsSubset(C[2], C[3]);
true
gap> A := [ RepetitionCode(4, GF(2)), EvenWeightSubcode( QRCode(17, GF(2)) ) ];
[ a cyclic [4,1,4]2 repetition code over GF(2), a cyclic [17,8,6]3..6 even weight subcode ]
gap> CX := ConstructionXCode(C, A);
a linear [148,23,53]43..74 Construction X code
gap> History(CX);
[ "a linear [148,23,53]43..74 Construction X code of", 
  "Base codes: [ a cyclic [127,15,55]41..62 BCH code, delta=55, b=1 over GF(2)\
, a cyclic [127,22,47..51]36..63 BCH code, delta=47, b=1 over GF(2), a linear \
[127,23,43]35..63 code defined by generator matrix over GF(2) ]", 
  "Auxiliary codes: [ a cyclic [4,1,4]2 repetition code over GF(2), a cyclic [\
17,8,6]3..6 even weight subcode ]" ]
</Example>
<!--
C1 := BCHCode(127, 43);
C2 := BCHCode(127, 47);
C3 := BCHCode(127, 55);
G1 := ShallowCopy( GeneratorMat(C2) );;
Append(G1, [ GeneratorMat(C1)[23] ]);;
C1 := GeneratorMatCode(G1, GF(2));
MinimumDistance(C1);
C := [ C1, C2, C3 ];
IsSubset(C[1], C[2]);
IsSubset(C[2], C[3]);
A := [ RepetitionCode(4, GF(2)), EvenWeightSubcode( QRCode(17, GF(2)) ) ];
CX := ConstructionXCode(C, A);
History(CX);
-->


<ManSection>
	<Func Name="ConstructionXXCode" Arg=" C1 C2 C3 A1 A2 "/>

	<Description>
		Consider a set of linear codes over field <M>F</M> of the same length, 
		<M>n</M>, <M>C_1=[n, k_1, d_1]</M>, <M>C_2=[n, k_2, d_2]</M> and <M>C_3=[n, k_3, d_3]</M>
		such that <M>C_2 \subset C_1</M>, <M>C_3 \subset C_1</M> and <M>C_4 = C_2 \cap C_3</M>.
		Given two auxiliary codes <M>A_1=[n_1, k_1-k_2, e_1]</M> and <M>A_2=[n_2, k_1-k_3, e_2]</M>
		over the same field <M>F</M>, there exists an <M>[n+n_1+n_2, k_1, d]</M> linear code
		<M>C_{XX}</M> over field <M>F</M>, where <M>d = \min\{d_4, d_3 + e_1, d_2 + e_2,
		d_1 + e_1 + e_2\}</M>.
		<P/>
		The codewords of <M>C_{XX}</M> can be partitioned into three sections <M>( v\;\|\;a\;\|\;b )</M>
		where <M>v</M> has length <M>n</M>, <M>a</M> has length <M>n_1</M> and <M>b</M> has length
		<M>n_2</M>. A codeword from Construction XX takes the following form:
		<List>
			<Item>
				<M>( v \; \| \; 0 \; \| \; 0 )</M> if <M>v \in C_4</M>
			</Item>
			<Item>
				<M>( v \; \| \; a_1 \; \| \; 0 )</M> if <M>v \in C_3 \backslash C_4</M>
			</Item>
			<Item>
				<M>( v \; \| \; 0 \; \| \; a_2 )</M> if <M>v \in C_2 \backslash C_4</M>
			</Item>
			<Item>
				<M>( v \; \| \; a_1 \; \| \; a_2 )</M> otherwise
			</Item>
		</List>
		For more information on Construction XX, refer to <Cite Key="Alltop84"/>.
	</Description>
</ManSection>

<Example>
gap> a := PrimitiveRoot(GF(32));
Z(2^5)
gap> f0 := MinimalPolynomial( GF(2), a^0 );
x_1+Z(2)^0
gap> f1 := MinimalPolynomial( GF(2), a^1 );
x_1^5+x_1^2+Z(2)^0
gap> f5 := MinimalPolynomial( GF(2), a^5 );
x_1^5+x_1^4+x_1^2+x_1+Z(2)^0
gap> C2 := CheckPolCode( f0 * f1, 31, GF(2) );; MinimumDistance(C2);; Display(C2);
a cyclic [31,6,15]10..13 code defined by check polynomial over GF(2)
gap> C3 := CheckPolCode( f0 * f5, 31, GF(2) );; MinimumDistance(C3);; Display(C3);
a cyclic [31,6,15]10..13 code defined by check polynomial over GF(2)
gap> C1 := UnionCode(C2, C3);; MinimumDistance(C1);; Display(C1);
a linear [31,11,11]7..11 union code of
U: a cyclic [31,6,15]10..13 code defined by check polynomial over GF(2)
V: a cyclic [31,6,15]10..13 code defined by check polynomial over GF(2)
gap> A1 := BestKnownLinearCode( 10, 5, GF(2) );
a linear [10,5,4]2..4 shortened code
gap> A2 := DualCode( RepetitionCode(6, GF(2)) );
a cyclic [6,5,2]1 dual code
gap> CXX:= ConstructionXXCode(C1, C2, C3, A1, A2 );
a linear [47,11,15..17]13..23 Construction XX code
gap> MinimumDistance(CXX);
17
gap> History(CXX);        
[ "a linear [47,11,17]13..23 Construction XX code of", 
  "C1: a cyclic [31,11,11]7..11 union code", 
  "C2: a cyclic [31,6,15]10..13 code defined by check polynomial over GF(2)", 
  "C3: a cyclic [31,6,15]10..13 code defined by check polynomial over GF(2)", 
  "A1: a linear [10,5,4]2..4 shortened code", 
  "A2: a cyclic [6,5,2]1 dual code" ]
</Example>
<!--
a := PrimitiveRoot(GF(32));
f0 := MinimalPolynomial( GF(2), a^0 );
f1 := MinimalPolynomial( GF(2), a^1 );
f5 := MinimalPolynomial( GF(2), a^5 );
C2 := CheckPolCode( f0 * f1, 31, GF(2) );; MinimumDistance(C2);; Display(C2);
C3 := CheckPolCode( f0 * f5, 31, GF(2) );; MinimumDistance(C3);; Display(C3);
C1 := UnionCode(C2, C3);; MinimumDistance(C1);; Display(C1);
A1 := BestKnownLinearCode( 10, 5, GF(2) );
A2 := DualCode( RepetitionCode(6, GF(2)) );
CXX:= ConstructionXXCode(C1, C2, C3, A1, A2 );
History(CXX);
-->

<ManSection>
	<Func Name="BZCode" Arg=" O I "/>

	<Description>
		Given a set of outer codes of the same length <M>O_i = [N, K_i, D_i]</M> over GF(<M>q^{e_i}</M>),
		where <M>i=1,2,\ldots,t</M> and a set of inner codes of the same length
		<M>I_i = [n, k_i, d_i]</M> over GF(<M>q</M>), <C>BZCode</C> returns a
		Blokh-Zyablov multilevel concatenated code
		with parameter <M>[ n \times N, \sum_{i=1}^t e_i \times K_i,
			\min_{i=1,\ldots,t}\{d_i \times D_i\} ]</M> over GF(<M>q</M>).
		<P/>
		Note that the set of inner codes must satisfy chain condition, i.e.
		<M>I_1 = [n, k_1, d_1] \subset I_2=[n, k_2, d_2] \subset \ldots \subset
			I_t=[n, k_t, d_t]</M> where <M>0=k_0 &lt; k_1 &lt; k_2 &lt; \ldots &lt; k_t</M>.
		The dimension of the inner codes must satisfy the condition <M>e_i = k_i - k_{i-1}</M>,
		where GF(<M>q^{e_i}</M>) is the field of the <M>i</M>th outer code.
		<P/>
		For more information on Blokh-Zyablov multilevel concatenated code, refer to
		<Cite Key="Brouwer98"/>.
	</Description>
</ManSection>

<ManSection>
	<Func Name="BZCodeNC" Arg=" O I "/>
	<Description>
		This function is the same as <C>BZCode</C>,
		except this version is faster as it does not estimate the covering radius of the code.
		Users are encouraged to use this version unless you are working on very small codes.
	</Description>
</ManSection>

<Example>
gap> #
gap> # Binary code
gap> #
gap> O := [ CyclicMDSCode(2,3,7), BestKnownLinearCode(9,5,GF(2)), CyclicMDSCode(2,3,4) ];
[ a cyclic [9,7,3]1 MDS code over GF(8), a linear [9,5,3]2..3 shortened code, 
  a cyclic [9,4,6]4..5 MDS code over GF(8) ]
gap> A := ExtendedCode( HammingCode(3,GF(2)) );;
gap> I := [ SubCode(A), A, DualCode( RepetitionCode(8, GF(2)) ) ];
[ a linear [8,3,4]3..4 subcode, a linear [8,4,4]2 extended code, a cyclic [8,7,2]1 dual code ]
gap> C := BZCodeNC(O, I);
a linear [72,38,12]0..72 Blokh Zyablov concatenated code
gap> #
gap> # Non binary code
gap> #
gap> O2 := ExtendedCode(GoppaCode(ConwayPolynomial(5,2), Elements(GF(5))));;
gap> O3 := ExtendedCode(GoppaCode(ConwayPolynomial(5,3), Elements(GF(5))));;
gap> O1 := DualCode( O3 );;
gap> MinimumDistance(O1);; MinimumDistance(O2);; MinimumDistance(O3);;
gap> Cy := CyclicCodes(5, GF(5));;
gap> for i in [4, 5] do; MinimumDistance(Cy[i]);; od;
gap> O  := [ O1, O2, O3 ];
[ a linear [6,4,3]1 dual code, a linear [6,3,4]2..3 extended code,
  a linear [6,2,5]3..4 extended code ]
gap> I  := [ Cy[5], Cy[4], Cy[3] ];
[ a cyclic [5,1,5]3..4 enumerated code over GF(5),
  a cyclic [5,2,4]2..3 enumerated code over GF(5),
  a cyclic [5,3,1..3]2 enumerated code over GF(5) ]
gap> C  := BZCodeNC( O, I );
a linear [30,9,5..15]0..30 Blokh Zyablov concatenated code
gap> MinimumDistance(C);
15
gap> History(C);
[ "a linear [30,9,15]0..30 Blokh Zyablov concatenated code of",
  "Inner codes: [ a cyclic [5,1,5]3..4 enumerated code over GF(5), a cyclic [5\
,2,4]2..3 enumerated code over GF(5), a cyclic [5,3,1..3]2 enumerated code ove\
r GF(5) ]",
  "Outer codes: [ a linear [6,4,3]1 dual code, a linear [6,3,4]2..3 extended c\
ode, a linear [6,2,5]3..4 extended code ]" ]
</Example>

<!--
#
# Binary code
#
O := [ CyclicMDSCode(2,3,7), BestKnownLinearCode(9,5,GF(2)), CyclicMDSCode(2,3,4) ];
A := ExtendedCode( HammingCode(3,GF(2)) );;
I := [ SubCode(A), A, DualCode( RepetitionCode(8, GF(2)) ) ];
C := BZCodeNC(O, I);
#
# Non binary code
#
O2 := ExtendedCode( GoppaCode(ConwayPolynomial(5,2), Elements(GF(5))) );;
O3 := ExtendedCode( GoppaCode(ConwayPolynomial(5,3), Elements(GF(5))) );;
O1 := DualCode( O3 );;
MinimumDistance(O1);; MinimumDistance(O2);; MinimumDistance(O3);;
Cy := CyclicCodes(5, GF(5));;
for i in [4, 5] do; MinimumDistance(Cy[i]);; od;
O  := [ O1, O2, O3 ];
I  := [ Cy[5], Cy[4], Cy[3] ];
C  := BZCodeNC( O, I );
MinimumDistance(C);
History(C);
-->

</Section>
</Chapter>


<Chapter>
<Heading>
Bounds on codes, special matrices and miscellaneous functions
</Heading>



In this chapter we describe functions that determine bounds on the size
and minimum distance of codes (Section
<Ref Label="Distance bounds on codes" Style="Number"/>), 
functions that determine bounds on the size
and covering radius of codes (Section
<Ref Label="Covering radius bounds on codes" Style="Number"/>), 
functions that
work with special matrices <Package>GUAVA</Package> needs for 
several codes (see
Section <Ref Label="Special matrices in GUAVA" Style="Number"/>),  
and constructing codes or performing calculations with codes 
(see Section 
<Ref Label="Miscellaneous functions" Style="Number"/>).


<Section>
<Heading>
Distance bounds on codes
</Heading>
<Label Name="Distance bounds on codes"/>


This  section describes the functions that calculate estimates for upper
bounds on the size and minimum distance of codes. Several algorithms are
known to compute a largest  number of words a code can have with  given
length and minimum distance. It is important however to understand that
in some cases the true upper bound is unknown.  A code which has a  size
equalto the calculated upper bound may not have been found.  However,
codes that have a larger size do not exist.
<P/>
A second way to obtain bounds is a table. In 
<Package>GUAVA</Package>, an extensive table
is implemented for linear codes over <M>GF(2)</M>, <M>GF(3)</M> 
and <M>GF(4)</M>. It contains bounds on the minimum distance for given
<!--word length and dimension.  For binary codes, it contains entries for 
word length less than or equal to <M>257</M>. For codes over <M>GF(3)</M>
and <M>GF(4)</M>, it contains entries for word length less than or 
equal to <M>130</M>. These tables have not been maintained since 1998.-->
word length and dimension.  It contains entries for word lengths less than
or equal to <M>257</M>, <M>243</M> and <M>256</M> for codes over <M>GF(2)</M>,
<M>GF(3)</M> and <M>GF(4)</M> respectively.
These entries were obtained from Brouwer's tables as of 11 May 2006.
For the latest information, please see
A. E. Brouwer's tables <Cite Key="Br"/> on the internet.

<P/>
Firstly, we describe functions that compute specific upper bounds 
on the code size (see 
<Ref Func="UpperBoundSingleton" Style="Number"/>,     
<Ref Func="UpperBoundHamming" Style="Number"/>,
<Ref Func="UpperBoundJohnson" Style="Number"/>,    
<Ref Func="UpperBoundPlotkin" Style="Number"/>,    
<Ref Func="UpperBoundElias" Style="Number"/>     and
<Ref Func="UpperBoundGriesmer" Style="Number"/>).
<P/>
Next we describe a function that computes 
<Package>GUAVA</Package>'s best upper bound on
the code size (see 
<Ref Func="UpperBound" Style="Number"/>).
<P/>
Then we describe two functions that compute a lower and upper bound on
the minimum distance of a code (see  
<Ref Func="LowerBoundMinimumDistance" Style="Number"/>  and
<Ref Func="UpperBoundMinimumDistance" Style="Number"/>).
<P/>
Finally, we describe a function that returns a lower and upper  bound  on
the minimum distance with given parameters and a description of how the
bounds were obtained (see 
<Ref Func="BoundsMinimumDistance" Style="Number"/>).

<Index>
bounds, Singleton
</Index>

<ManSection>
<Func Name="UpperBoundSingleton" Arg=" n d q "/>

<Description>
<C>UpperBoundSingleton</C> returns the Singleton bound for a code of 
length <A>n</A>, minimum distance <A>d</A> over a field of size
<A>q</A>. This bound is based on the shortening of codes.  
By shortening an <M>(n,  M, d)</M> code <M>d-1</M> times,  
an <M>(n-d+1,M,1)</M> code results, with <M>M  \leq  q^{n-d+1}</M>
(see
<Ref Func="ShortenedCode" Style="Number"/>). Thus

<Display>
M \leq q^{n-d+1}.
</Display>

<Index>
maximum distance separable
</Index>
Codes that meet this bound are called <E>maximum distance separable</E> 
(see
<Ref Func="IsMDSCode" Style="Number"/>).
</Description>
</ManSection>

<Example>
gap> UpperBoundSingleton(4, 3, 5);
25
gap> C := ReedSolomonCode(4,3);; Size(C);
25
gap> IsMDSCode(C);
true 
</Example>

<Index>
bounds, Hamming
</Index>
<Index>
bounds, sphere packing bound
</Index>
<Index>
perfect
</Index>

<ManSection>
<Func Name="UpperBoundHamming" Arg=" n d q "/>

<Description>
The Hamming bound (also known as the <E>sphere packing bound</E>) 
returns an upper bound on the size of a code of length <A>n</A>, 
minimum distance <A>d</A>, over a field of size <A>q</A>. 
The Hamming bound is obtained by dividing the contents
of the entire space <M>GF(q)^n</M> 
by the contents of a ball with radius
<M>\lfloor(d-1) / 2\rfloor</M>.  As all these balls are disjoint, 
they can never contain more than the whole vector  space.  
<Display>
M \leq {q^n \over V(n,e)},
</Display>
where <M>M</M> is the maxmimum number of codewords and 
<M>V(n,e)</M>
is equal to the contents of a ball of radius <M>e</M> (see
<Ref Func="SphereContent" Style="Number"/>).  
This bound is useful for small values of <A>d</A>.  
Codes for which equality holds are called <E>perfect</E> 
(see <Ref Func="IsPerfectCode" Style="Number"/>).
</Description>
</ManSection>

<Example>
gap> UpperBoundHamming( 15, 3, 2 );
2048
gap> C := HammingCode( 4, GF(2) );
a linear [15,11,3]1 Hamming (4,2) code over GF(2)
gap> Size( C );
2048 
</Example>


<Index>bounds, Johnson
</Index>


<ManSection>
<Func Name="UpperBoundJohnson" Arg=" n d "/>

<Description>
The Johnson bound is an improved version of the Hamming bound (see
<Ref Func="UpperBoundHamming" Style="Number"/>).   
In addition to the Hamming bound, it takes into
account the elements of the space outside the balls of radius 
<M>e</M> around the elements of the code. 
The Johnson bound only works for binary codes.
</Description>
</ManSection>

<Example>
gap> UpperBoundJohnson( 13, 5 );
77
gap> UpperBoundHamming( 13, 5, 2);
89   # in this case the Johnson bound is better 
</Example>

<Index>bounds, Plotkin
</Index>
<ManSection>
<Func Name="UpperBoundPlotkin" Arg=" n d q "/>

<Description>
The function <C>UpperBoundPlotkin</C> calculates the sum of the
distances of all ordered pairs of different codewords. 
It is based on the fact that the minimum distance is at most 
equal to the average distance. It is a
good bound if the weights of the codewords do not differ much. It results
in: 

<Display>
M \leq {d \over {d-(1-1/q)n}},
</Display>
where <M>M</M> is the maximum number
of codewords.  In this case, <A>d</A>  must be larger than 
<M>(1-1/q)n</M>, but by shortening the code, the 
case <M>d \ \ \langle\ \  (1-1/q)n</M> is covered.
</Description>
</ManSection>

<Example>
gap> UpperBoundPlotkin( 15, 7, 2 );
32
gap> C := BCHCode( 15, 7, GF(2) );
a cyclic [15,5,7]5 BCH code, delta=7, b=1 over GF(2)
gap> Size(C);
32
gap> WeightDistribution(C);
[ 1, 0, 0, 0, 0, 0, 0, 15, 15, 0, 0, 0, 0, 0, 0, 1 ] 
</Example>
<!--
UpperBoundPlotkin( 15, 7, 2 );
C := BCHCode( 15, 7, GF(2) );
Size(C);
WeightDistribution(C);
-->

<Index>
bounds, Elias
</Index>
<ManSection>
<Func Name="UpperBoundElias" Arg=" n d q "/>

<Description>
The Elias bound is an improvement of the Plotkin bound (see
<Ref Func="UpperBoundPlotkin" Style="Number"/>) 
for large codes. Subcodes are used to decrease the
size of the code, in this case the subcode of all codewords within a
certain ball. This bound is useful  for large codes with relatively small
minimum distances.
</Description>
</ManSection>

<Example>
gap> UpperBoundPlotkin( 16, 3, 2 );
12288
gap> UpperBoundElias( 16, 3, 2 );
10280 
gap> UpperBoundElias( 20, 10, 3 );
16255
</Example>


<Index>
bounds, Griesmer
</Index>
<ManSection>
<Func Name="UpperBoundGriesmer" Arg=" n d q "/>

<Description>
The Griesmer bound is valid only for linear codes.  It is obtained by
counting the number of equal symbols in each row of the generator matrix
of the code. By omitting the coordinates in which all rows have a zero, a
smaller code results.  The Griesmer bound is obtained by repeating this
proces until a trivial code is left in the end.
</Description>
</ManSection>

<Example>
gap> UpperBoundGriesmer( 13, 5, 2 );
64
gap> UpperBoundGriesmer( 18, 9, 2 );
8        # the maximum number of words for a linear code is 8
gap> Size( PuncturedCode( HadamardCode( 20, 1 ) ) );
20       # this non-linear code has 20 elements 
</Example>
<!--
UpperBoundGriesmer( 13, 5, 2 );
UpperBoundGriesmer( 18, 9, 2 );
Size( PuncturedCode( HadamardCode( 20, 1 ) ) );
-->

<Index>
Griesmer code
</Index>

<ManSection>
<Func Name="IsGriesmerCode" Arg=" C "/>

<Description>
<C>IsGriesmerCode</C> returns `true' if a linear code <A>C</A>
is a Griesmer code, and `false' otherwise.
A code is called <E>Griesmer</E> if its length satisfies

<Display>
n = g[k,d] = \sum_{i=0}^{k-1} \lceil \frac{d}{q^i} \rceil.
</Display>
</Description>
</ManSection>

<Example>
gap> IsGriesmerCode( HammingCode( 3, GF(2) ) );
true
gap> IsGriesmerCode( BCHCode( 17, 2, GF(2) ) );
false 
</Example>


<Index>
<M>A(n,d)</M>
</Index>

<ManSection>
<Func Name="UpperBound" Arg=" n d q "/>

<Description>
<C>UpperBound</C> returns the best known upper bound 
<M>A(n,d)</M> for the size of a code of length <A>n</A>, 
minimum distance <A>d</A> over a  field of size <A>q</A>.
The function <C>UpperBound</C> first checks for 
trivial cases (like <M>d=1</M> or <M>n=d</M>), and if the 
value is in the  built-in table. Then it calculates
the minimum value of the upper bound using the methods of Singleton (see
<Ref Func="UpperBoundSingleton" Style="Number"/>),  Hamming (see 
<Ref Func="UpperBoundHamming" Style="Number"/>), Johnson  (see
<Ref Func="UpperBoundJohnson" Style="Number"/>), Plotkin  (see  
<Ref Func="UpperBoundPlotkin" Style="Number"/>)  and Elias (see
<Ref Func="UpperBoundElias" Style="Number"/>).  If the code is binary, 
<M>A(n, 2\cdot \ell-1) =  A(n+1,2\cdot \ell)</M>, so the 
<C>UpperBound</C> takes the minimum of the values obtained from
all methods for the parameters 
<M>(n, 2\cdot\ell-1)</M> and <M>(n+1, 2\cdot \ell)</M>.
</Description>
</ManSection>

<Example>
gap> UpperBound( 10, 3, 2 );
85
gap> UpperBound( 25, 9, 8 );
1211778792827540 
</Example>


<ManSection>
<Func Name="LowerBoundMinimumDistance" Arg=" C "/>

<Description>
In this form, <C>LowerBoundMinimumDistance</C>
returns a lower bound for the minimum distance of code <A>C</A>.
<P/>
This command can also be called using the syntax
<C>LowerBoundMinimumDistance( n, k, F )</C>.
In this form, <C>LowerBoundMinimumDistance</C> returns a 
lower bound for the minimum distance of the best known linear
code of length <A>n</A>, dimension <A>k</A> over field <A>F</A>.
It uses the  mechanism explained in section
<Ref Label="BoundsMinimumDistance" Style="Number"/>.
</Description>
</ManSection>

<Example>
gap> C := BCHCode( 45, 7 );
a cyclic [45,23,7..9]6..16 BCH code, delta=7, b=1 over GF(2)
gap> LowerBoundMinimumDistance( C );
7     # designed distance is lower bound for minimum distance 
gap> LowerBoundMinimumDistance( 45, 23, GF(2) );
10 
</Example>
<!--
C := BCHCode( 45, 7 );
LowerBoundMinimumDistance( C );
LowerBoundMinimumDistance( 45, 23, GF(2) );
-->

<Index>
 bound, Gilbert-Varshamov lower
</Index>

<ManSection>
<Func Name="LowerBoundGilbertVarshamov" Arg=" n d q "/>

<Description>
This is the lower bound on the size of a linear code 
due (independently) to Gilbert and Varshamov. It says that for each 
<A>n</A> and <A>d</A>, there exists a linear code 
having length  <M>n</M> and minimum distance <M>d</M> at least of size
<M>q^k</M>, where <M>k</M> is the largest integer
such that <M>q^k &lt; q^{n}/</M><C>SphereContent</C><M>(n-1,d-2,GF(q))</M>. 
</Description>
</ManSection>

<Example>
gap> LowerBoundGilbertVarshamov(24,8,2);
64
gap> LowerBoundGilbertVarshamov(7,3,2);
16
gap> LowerBoundMinimumDistance(7,4,2);
3
gap> LowerBoundGilbertVarshamov(3,3,2);
1
gap> LowerBoundMinimumDistance(3,3,2);
1
gap> LowerBoundGilbertVarshamov(25,10,2);
16
</Example>
<!--
LowerBoundGilbertVarshamov(3,2,2);
LowerBoundGilbertVarshamov(3,3,2);
LowerBoundMinimumDistance(3,3,2);
LowerBoundMinimumDistance(3,2,2);
LowerBoundGilbertVarshamov(25,10,2);
-->

<Index>
 bound, sphere packing lower
</Index>

<ManSection>
<Func Name="LowerBoundSpherePacking" Arg=" n d q "/>

<Description>
This is the (weaker) Gilbert-Varshamov bound valid for 
unrestricted codes over an alphabet of 
size <A>q</A> (where <A>q</A> is an integer &gt; 1).
It says that for each <A>n</A> and 
<A>r</A>, there exists an unrestricted code at least of size
<M>q^n/</M><C>SphereContent</C><M>(n,d,GF(q))</M>
minimum distance <M>d</M>. 
</Description>
</ManSection>

<Example>
gap> LowerBoundSpherePacking(3,2,2);
2
gap> LowerBoundSpherePacking(3,3,2);
1
</Example>
<!--
LowerBoundSpherePacking(3,2,2);
LowerBoundSpherePacking(3,3,2);
-->


<ManSection>
<Func Name="UpperBoundMinimumDistance" Arg=" C "/>

<Description>
In this form, <C>UpperBoundMinimumDistance</C> returns an upper bound for the
minimum distance of code <A>C</A>. For unrestricted codes, it just returns the
word length. For linear codes, it takes the minimum of the possibly known
value from the method of construction, the weight of the generators, and
the value from the table (see 
<Ref Label="BoundsMinimumDistance" Style="Number"/>).
<P/>
This command can also be called using the syntax
<C>UpperBoundMinimumDistance( n, k, F )</C>.
In this form, <C>UpperBoundMinimumDistance</C> returns an upper bound for the
minimum distance of the best known linear code of length 
<A>n</A>, dimension <A>k</A>  over field <A>F</A>.  
It uses the mechanism explained in section
<Ref Label="BoundsMinimumDistance" Style="Number"/>.
</Description>
</ManSection>

<Example>
gap> C := BCHCode( 45, 7 );;
gap> UpperBoundMinimumDistance( C );
9 
gap> UpperBoundMinimumDistance( 45, 23, GF(2) );
11 
</Example>
<!--
C := BCHCode( 45, 7 );;
UpperBoundMinimumDistance( C );
UpperBoundMinimumDistance( 45, 23, GF(2) );
-->

<ManSection>
<Func Name="BoundsMinimumDistance" Arg=" n k F "/>

<Description>
The function <C>BoundsMinimumDistance</C> calculates a lower and upper bound
for the minimum distance of an optimal linear code with word length 
<A>n</A>, dimension <A>k</A> over field <A>F</A>. The function 
returns a record with the two bounds and an explanation for 
each bound. The function <C>Display</C> can be
used to show the explanations.
<P/>
The values for the lower and upper bound are obtained from a
table. <Package>GUAVA</Package> has tables containing lower 
and upper bounds for <M>q=2 (n \leq 257), <!--3, 4 (n \leq 130)</M>.  
(Current as of 1998 - now out of date.)-->
3 (n \leq 243), 4 (n \leq 256)</M>. (Current as of 11 May 2006.)
These tables were derived from the table of Brouwer. 
(See <Cite Key="Br"/>,
<URL>https://www.codetables.de</URL> for the most
recent data.)
For codes over other fields and for larger
word lengths, trivial bounds are used.
<P/>
The resulting record can be used in the function 
<C>BestKnownLinearCode</C> 
(see <Ref Func="BestKnownLinearCode" Style="Number"/>) 
to construct a code with minimum distance
equal to the lower bound.
</Description>
</ManSection>

<Example>
gap> bounds := BoundsMinimumDistance( 7, 3 );; DisplayBoundsInfo( bounds );
an optimal linear [7,3,d] code over GF(2) has d=4
------------------------------------------------------------------------------
Lb(7,3)=4, by shortening of:
Lb(8,4)=4, u u+v construction of C1 and C2:
Lb(4,3)=2, dual of the repetition code
Lb(4,1)=4, repetition code
------------------------------------------------------------------------------
Ub(7,3)=4, Griesmer bound
# The lower bound is equal to the upper bound, so a code with
# these parameters is optimal.
gap> C := BestKnownLinearCode( bounds );; Display( C );
a linear [7,3,4]2..3 shortened code of
a linear [8,4,4]2 U U+V construction code of
U: a cyclic [4,3,2]1 dual code of
   a cyclic [4,1,4]2 repetition code over GF(2)
V: a cyclic [4,1,4]2 repetition code over GF(2)
</Example>
<!--
bounds := BoundsMinimumDistance( 7, 3 );; 
DisplayBoundsInfo( bounds );
C := BestKnownLinearCode( bounds );; 
Display( C );
-->

</Section>


<Section>
<Heading>
Covering radius bounds on codes
</Heading>
<Label Name="Covering radius bounds on codes"/>


<ManSection>
<Func Name="BoundsCoveringRadius" Arg=" C "/>

<Description>
<C>BoundsCoveringRadius</C> returns a list of integers.
The first entry of this list is the maximum of some lower bounds
for the covering radius of <A>C</A>,
the last entry the minimum of some upper bounds of <A>C</A>.
<P/>
If the covering radius of <A>C</A> is known, a list of length 1 is
returned.
<C>BoundsCoveringRadius</C> makes use of the functions
<C>GeneralLowerBoundCoveringRadius</C> and
<C>GeneralUpperBoundCoveringRadius</C>.
</Description>
</ManSection>

<Example>
gap> BoundsCoveringRadius( BCHCode( 17, 3, GF(2) ) );
[ 3 .. 4 ]
gap> BoundsCoveringRadius( HammingCode( 5, GF(2) ) );
[ 1 ] 
</Example>


<ManSection>
<Func Name="IncreaseCoveringRadiusLowerBound" Arg=" C [stopdist] [startword] "/>

<Description>
<C>IncreaseCoveringRadiusLowerBound</C> tries to increase the lower 
bound of
the covering radius of <A>C</A>. It does this by means of a probabilistic
algorithm.  This algorithm takes a random word in <M>GF(q)^n</M>   (or
<A>startword</A> if it is specified), and,  by changing random coordinates,
tries to get as far from <A>C</A> as possible.  If changing a coordinate
finds a word that has a larger distance to the code than the previous
one, the change is made permanent, and the algorithm starts all over
again. If changing a coordinate does not find a coset leader that is
further away from the code, then the change is made permanent with a
chance of 1 in 100, if it gets the word closer to the code, or with a
chance of 1 in 10, if the word stays at the same distance. Otherwise, the
algorithm starts again with the same word as before.
<P/>
If the algorithm did not allow changes that decrease the distance to  the
code, it might get stuck in a sub-optimal situation  (the coset leader
corresponding to such a situation - i.e.  no coordinate of this coset
leader can be changed in such a way that we get at a larger distance from
the code - is called an <E>orphan</E>).
<P/>
If the algorithm finds a word that has distance <A>stopdist</A> to the
code, it ends and returns that word,  which can be used for further
investigations.
<P/>
The variable <A>InfoCoveringRadius</A> can be set to 
<A>Print</A> to print the maximum distance reached so far every 
1000 runs.  The algorithm can be interrupted with <B>ctrl-C</B>, 
allowing the user to look at the word that is
currently being examined (called `current'), or to change the chances
that the new word is made permanent (these are called  
`staychance'  and `downchance'). If one of these variables is 
<M>i</M>, then it corresponds with
a <M>i</M> in 100 chance.
<P/>
At the moment,  the  algorithm  is  only  useful for codes with small
dimension, where small means that the elements of the code fit in the
memory. It works with larger codes, however, but when you  use it for
codes with large dimension, you should be <E>very</E> patient. If running  the
algorithm quits GAP (due to  memory  problems),  you can change the
global variable <A>CRMemSize</A> to a lower value.  This might cause the
algorithm to run slower, but without quitting GAP.  The only way  to
find out the best value of <A>CRMemSize</A> is by experimenting.
</Description>
</ManSection>

<Example>
gap> C:=RandomLinearCode(10,5,GF(2));
a  [10,5,?] randomly generated code over GF(2)
gap> IncreaseCoveringRadiusLowerBound(C,10);
Number of runs: 1000  best distance so far: 3
Number of runs: 2000  best distance so far: 3
Number of changes: 100
Number of runs: 3000  best distance so far: 3
Number of runs: 4000  best distance so far: 3
Number of runs: 5000  best distance so far: 3
Number of runs: 6000  best distance so far: 3
Number of runs: 7000  best distance so far: 3
Number of changes: 200
Number of runs: 8000  best distance so far: 3
Number of runs: 9000  best distance so far: 3
Number of runs: 10000  best distance so far: 3
Number of changes: 300
Number of runs: 11000  best distance so far: 3
Number of runs: 12000  best distance so far: 3
Number of runs: 13000  best distance so far: 3
Number of changes: 400
Number of runs: 14000  best distance so far: 3
user interrupt at... 
#
# used ctrl-c to break out of execution
#
... called from 
IncreaseCoveringRadiusLowerBound( code, -1, current ) called from
 function( arguments ) called from read-eval-loop
Entering break read-eval-print loop ...
you can 'quit;' to quit to outer loop, or
you can 'return;' to continue
brk> current;
[ Z(2)^0, Z(2)^0, Z(2)^0, Z(2)^0, 0*Z(2), Z(2)^0, 0*Z(2), Z(2)^0, 0*Z(2), Z(2)^0 ]
brk>
gap> CoveringRadius(C);
3

</Example>
<!--
C:=RandomLinearCode(10,5,GF(2));
IncreaseCoveringRadiusLowerBound(C,10);
current;
CoveringRadius(C);
-->


<ManSection>
<Func Name="ExhaustiveSearchCoveringRadius" Arg=" C "/>

<Description>
<C>ExhaustiveSearchCoveringRadius</C> does an exhaustive search to find the
covering radius of <A>C</A>. Every time a coset leader of a coset with
weight <M>w</M> is found, the function tries to find a coset leader of a coset
with weight <M>w+1</M>. It does this by enumerating all words of 
weight <M>w+1</M>,
and checking whether a word is a coset leader. The start weight is the
current known lower bound on the covering radius.
</Description>
</ManSection>

<Example>
gap> C:=RandomLinearCode(10,5,GF(2));
a  [10,5,?] randomly generated code over GF(2)
gap> ExhaustiveSearchCoveringRadius(C);
Trying 3 ...
[ 3 .. 5 ]
gap> CoveringRadius(C);
3

</Example>
<!--
C:=RandomLinearCode(10,5,GF(2));
ExhaustiveSearchCoveringRadius(C);
CoveringRadius(C);
-->


<ManSection>
<Func Name="GeneralLowerBoundCoveringRadius" Arg=" C "/>

<Description>
<C>GeneralLowerBoundCoveringRadius</C> returns a lower bound on the covering
radius of <A>C</A>. It uses as many functions which names start with
<C>LowerBoundCoveringRadius</C> as possible to find the best known lower bound
(at least that <Package>GUAVA</Package> knows of) 
together with tables for the covering
radius of binary linear codes with length not greater than <M>64</M>.
</Description>
</ManSection>

<Example>
gap> C:=RandomLinearCode(10,5,GF(2));
a  [10,5,?] randomly generated code over GF(2)
gap> GeneralLowerBoundCoveringRadius(C);
2
gap> CoveringRadius(C);
3

</Example>
<!--
C:=RandomLinearCode(10,5,GF(2));
GeneralLowerBoundCoveringRadius(C);
CoveringRadius(C);
-->

<ManSection>
<Func Name="GeneralUpperBoundCoveringRadius" Arg=" C "/>

<Description>
<C>GeneralUpperBoundCoveringRadius</C> returns an upper bound on the
covering radius of <A>C</A>. It uses as many functions which
names start with <C>UpperBoundCoveringRadius</C> 
as possible to find the best known upper bound
(at least that <Package>GUAVA</Package> knows of).
</Description>
</ManSection>

<Example>
gap> C:=RandomLinearCode(10,5,GF(2));
a  [10,5,?] randomly generated code over GF(2)
gap> GeneralUpperBoundCoveringRadius(C);
4
gap> CoveringRadius(C);
3

</Example>

<ManSection>
<Func Name="LowerBoundCoveringRadiusSphereCovering" Arg=" n M [F] false "/>

<Description>
This command can also be called using the syntax
<C>LowerBoundCoveringRadiusSphereCovering( n, r, [F,] true )</C>.
If the last argument of <C>LowerBoundCoveringRadiusSphereCovering</C> is
<A>false</A>, then it returns a lower bound for the covering radius of a
code of size <A>M</A> and length <A>n</A>.
Otherwise, it returns a lower bound for the size of a code of length
<A>n</A> and covering radius <A>r</A>.
<P/>
<A>F</A> is the field over which the code is defined. 
If <A>F</A> is omitted, it is
assumed that the code is over <M>GF(2)</M>.
The bound is computed according to the sphere covering bound:
<Display>
M \cdot V_q(n,r) \geq q^n
</Display>
where <M>V_q(n,r)</M> is the size of a sphere of radius 
<M>r</M> in <M>GF(q)^n</M>.
</Description>
</ManSection>

<Example>
gap> C:=RandomLinearCode(10,5,GF(2));
a  [10,5,?] randomly generated code over GF(2)
gap> Size(C);
32
gap> CoveringRadius(C);
3
gap> LowerBoundCoveringRadiusSphereCovering(10,32,GF(2),false);
2
gap> LowerBoundCoveringRadiusSphereCovering(10,3,GF(2),true);
6

</Example>
<!--
C:=RandomLinearCode(10,5,GF(2));
Size(C);
CoveringRadius(C);
LowerBoundCoveringRadiusSphereCovering(10,32,GF(2),false);
LowerBoundCoveringRadiusSphereCovering(10,3,GF(2),true);
-->


<ManSection>
<Func Name="LowerBoundCoveringRadiusVanWee1" Arg=" n M [F] false "/>

<Description>
This command can also be called using the syntax
<C>LowerBoundCoveringRadiusVanWee1( n, r, [F,] true )</C>.
If the last argument of <C>LowerBoundCoveringRadiusVanWee1</C> is
<A>false</A>, then it returns a lower bound for the covering radius of a
code of size <A>M</A> and length <A>n</A>.
Otherwise, it returns a lower bound for the size of a code of length
<A>n</A> and covering radius <A>r</A>.
<P/>
<A>F</A> is the field over which the code is defined. 
If <A>F</A> is omitted, it is assumed that the code is over <M>GF(2)</M>.
<P/>
The Van Wee bound is an improvement of the sphere covering bound:
<Display>
M \cdot \left\{ V_q(n,r) -
\frac{{n \choose r}}{\lceil\frac{n-r}{r+1}\rceil}
\left(\left\lceil\frac{n+1}{r+1}\right\rceil - \frac{n+1}{r+1}\right)
\right\} \geq q^n
</Display>
</Description>
</ManSection>

<Example>
gap> C:=RandomLinearCode(10,5,GF(2));
a  [10,5,?] randomly generated code over GF(2)
gap> Size(C);
32
gap> CoveringRadius(C);
3
gap> LowerBoundCoveringRadiusVanWee1(10,32,GF(2),false);
2
gap> LowerBoundCoveringRadiusVanWee1(10,3,GF(2),true);
6

</Example>
<!--
C:=RandomLinearCode(10,5,GF(2));
Size(C);
CoveringRadius(C);
LowerBoundCoveringRadiusVanWee1(10,32,GF(2),false);
LowerBoundCoveringRadiusVanWee1(10,3,GF(2),true);
-->


<ManSection>
<Func Name="LowerBoundCoveringRadiusVanWee2" Arg=" n M false "/>

<Description>
This command can also be called using the syntax
<C>LowerBoundCoveringRadiusVanWee2( n, r [,true] )</C>.
If the last argument of <C>LowerBoundCoveringRadiusVanWee2</C> 
is <A>false</A>,
then it returns a lower bound for the covering radius of a code of size
<A>M</A> and length <A>n</A>. Otherwise, it returns a lower 
bound for the size of a code of length <A>n</A> and 
covering radius <A>r</A>.
<P/>
This bound only works for binary codes. It is based on the following
inequality:
<Display>
M \cdot \frac{\left( \left( V_2(n,2) - \frac{1}{2}(r+2)(r-1) \right)
V_2(n,r) + \varepsilon
V_2(n,r-2) \right)}
{(V_2(n,2) - \frac{1}{2}(r+2)(r-1) + \varepsilon)}
\geq 2^n,
</Display>
where

<Display>
\varepsilon = {r+2 \choose 2} \left\lceil
{n-r+1 \choose 2} / {r+2 \choose 2} \right\rceil
- {n-r+1 \choose 2}.
</Display>
</Description>
</ManSection>

<Example>
gap> C:=RandomLinearCode(10,5,GF(2));
a  [10,5,?] randomly generated code over GF(2)
gap> Size(C);
32
gap> CoveringRadius(C);
3
gap> LowerBoundCoveringRadiusVanWee2(10,32,false);
2
gap> LowerBoundCoveringRadiusVanWee2(10,3,true);
7

</Example>
<!--
C:=RandomLinearCode(10,5,GF(2));
Size(C);
CoveringRadius(C);
LowerBoundCoveringRadiusVanWee2(10,32,false);
LowerBoundCoveringRadiusVanWee2(10,3,true);
-->


<ManSection>
<Func Name="LowerBoundCoveringRadiusCountingExcess" Arg=" n M false "/>

<Description>
This command can also be called with
<C>LowerBoundCoveringRadiusCountingExcess( n, r [,true] )</C>.
If the last argument of <C>LowerBoundCoveringRadiusCountingExcess</C> is
<A>false</A>, then it returns a lower bound for the covering radius of a  code
of size <A>M</A> and length <A>n</A>. Otherwise, it returns a 
lower bound for the size of a code of length <A>n</A> and 
covering radius <A>r</A>.
<P/>
This bound only works for binary codes. It is based on the following
inequality:
<Display>
M \cdot \left( \rho V_2(n,r) + \varepsilon V_2(n,r-1) \right) \geq
(\rho + \varepsilon) 2^n,
</Display>
where

<Display>
\varepsilon = (r+1) \left\lceil\frac{n+1}{r+1}\right\rceil - (n+1)
</Display>
and

<Display>
\rho = \left\{
\begin{array}{l}
n-3+\frac{2}{n}, \ \ \  \ \ \  {\rm if}\   r = 2\\
n-r-1  ,        \ \ \  \ \ \   {\rm if}\   r \geq 3 .
\end{array}
\right.
</Display>
</Description>
</ManSection>

<Example>
gap> C:=RandomLinearCode(10,5,GF(2));
a  [10,5,?] randomly generated code over GF(2)
gap> Size(C);
32
gap> CoveringRadius(C);
3
gap> LowerBoundCoveringRadiusCountingExcess(10,32,false);
0
gap> LowerBoundCoveringRadiusCountingExcess(10,3,true);
7

</Example>
<!--
C:=RandomLinearCode(10,5,GF(2));
Size(C);
CoveringRadius(C);
LowerBoundCoveringRadiusCountingExcess(10,32,false);
LowerBoundCoveringRadiusCountingExcess(10,3,true);
-->



<ManSection>
<Func Name="LowerBoundCoveringRadiusEmbedded1" Arg=" n M false "/>

<Description>
This command can also be called with
<C>LowerBoundCoveringRadiusEmbedded1( n, r [,true] )</C>.
If the last argument of <C>LowerBoundCoveringRadiusEmbedded1</C> 
is 'false', then it returns a lower bound for the 
covering radius of a code of size <A>M</A> and length 
<A>n</A>. Otherwise, it returns a lower bound for the size of a
code of length <A>n</A> and covering radius <A>r</A>.
<P/>
This bound only works for binary codes. It is based on the following
inequality:

<Display>
M \cdot \left( V_2(n,r) - {2r \choose r} \right) \geq
2^n - A( n, 2r+1 ) {2r \choose r},
</Display>
where <M>A(n,d)</M> denotes the maximal cardinality 
of a (binary) code of length <M>n</M> and minimum distance 
<M>d</M>. The function <C>UpperBound</C> is used to
compute this value.
<P/>
Sometimes <C>LowerBoundCoveringRadiusEmbedded1</C> is better than
<C>LowerBoundCoveringRadiusEmbedded2</C>, sometimes it is the 
other way around.
</Description>
</ManSection>

<Example>
gap> C:=RandomLinearCode(10,5,GF(2));
a  [10,5,?] randomly generated code over GF(2)
gap> Size(C);
32
gap> CoveringRadius(C);
3
gap> LowerBoundCoveringRadiusEmbedded1(10,32,false);
2
gap> LowerBoundCoveringRadiusEmbedded1(10,3,true);
7

</Example>
<!--
C:=RandomLinearCode(10,5,GF(2));
Size(C);
CoveringRadius(C);
LowerBoundCoveringRadiusEmbedded1(10,32,false);
LowerBoundCoveringRadiusEmbedded1(10,3,true);
-->


<ManSection>
<Func Name="LowerBoundCoveringRadiusEmbedded2" Arg=" n M false "/>

<Description>
This command can also be called with
<C>LowerBoundCoveringRadiusEmbedded2( n, r [,true] )</C>.
If the last argument of <C>LowerBoundCoveringRadiusEmbedded2</C> 
is 'false',
then it returns a lower bound for the covering radius of a code  of  size
<A>M</A> and length <A>n</A>. Otherwise, it returns a 
lower bound for the size of a code of length <A>n</A> 
and covering radius <A>r</A>.
<P/>
This bound only works for binary codes. It is based on the following
inequality:

<Display>
M \cdot \left( V_2(n,r) - \frac{3}{2} {2r \choose r} \right) \geq
2^n - 2A( n, 2r+1 ) {2r \choose r},
</Display>
where <M>A(n,d)</M> denotes the maximal cardinality  
of a (binary) code of length <M>n</M> and minimum distance 
<M>d</M>. The function <C>UpperBound</C> is used to
compute this value.
<P/>
Sometimes <C>LowerBoundCoveringRadiusEmbedded1</C> is better than
<C>LowerBoundCoveringRadiusEmbedded2</C>, sometimes it is the 
other way around.
</Description>
</ManSection>

<Example>
gap> C:=RandomLinearCode(15,5,GF(2));
a  [15,5,?] randomly generated code over GF(2)
gap> Size(C);
32
gap> CoveringRadius(C);
6
gap> LowerBoundCoveringRadiusEmbedded2(10,32,false);
2
gap> LowerBoundCoveringRadiusEmbedded2(10,3,true);
7

</Example>

<ManSection>
<Func Name="LowerBoundCoveringRadiusInduction" Arg=" n r "/>

<Description>
<C>LowerBoundCoveringRadiusInduction</C> returns a lower 
bound for the size of a code with length <A>n</A> and 
covering radius <A>r</A>.
<P/>
If <M>n = 2r+2</M> and <M>r \geq 1</M>, the returned 
value is <M>4</M>.
<P/>
If <M>n = 2r+3</M> and <M>r \geq 1</M>, the returned 
value is <M>7</M>.
<P/>
If <M>n = 2r+4</M> and <M>r \geq 4</M>, the returned 
value is <M>8</M>.
<P/>
Otherwise, <M>0</M> is returned.
</Description>
</ManSection>

<Example>
gap> C:=RandomLinearCode(15,5,GF(2));
a  [15,5,?] randomly generated code over GF(2)
gap> CoveringRadius(C);
5
gap> LowerBoundCoveringRadiusInduction(15,6);
7

</Example>
<!--
C:=RandomLinearCode(15,5,GF(2));
CoveringRadius(C);
LowerBoundCoveringRadiusInduction(15,6);
-->


<ManSection>
<Func Name="UpperBoundCoveringRadiusRedundancy" Arg=" C "/>

<Description>
<C>UpperBoundCoveringRadiusRedundancy</C> returns the 
redundancy of <A>C</A> as an upper bound for the covering 
radius of <A>C</A>. <A>C</A> must be a linear code.
</Description>
</ManSection>

<Index>
external distance
</Index>

<Example>
gap> C:=RandomLinearCode(15,5,GF(2));
a  [15,5,?] randomly generated code over GF(2)
gap> CoveringRadius(C);
5
gap> UpperBoundCoveringRadiusRedundancy(C);
10

</Example>
<!--
C:=RandomLinearCode(15,5,GF(2));
CoveringRadius(C);
UpperBoundCoveringRadiusRedundancy(C);
-->


<ManSection>
<Func Name="UpperBoundCoveringRadiusDelsarte" Arg=" C "/>

<Description>
<C>UpperBoundCoveringRadiusDelsarte</C> returns an upper bound 
for the covering radius of <A>C</A>. This upper bound is equal
to the external distance of <A>C</A>, this is the minimum 
distance of the dual code, if <A>C</A> is a linear code.
<P/>
This is described in Theorem 11.3.3 of <Cite Key="HP03"/>.
</Description>
</ManSection>

<Example>
gap> C:=RandomLinearCode(15,5,GF(2));
a  [15,5,?] randomly generated code over GF(2)
gap> CoveringRadius(C);
5
gap> UpperBoundCoveringRadiusDelsarte(C);
13
</Example>
<!--
C:=RandomLinearCode(15,5,GF(2));
CoveringRadius(C);
UpperBoundCoveringRadiusDelsarte(C);
-->


<ManSection>
<Func Name="UpperBoundCoveringRadiusStrength" Arg=" C "/>

<Description>
<C>UpperBoundCoveringRadiusStrength</C> returns an upper bound
for the covering radius of <A>C</A>.
<P/>
First the code is punctured at the zero coordinates (i.e. the coordinates
where all codewords have a zero). If the remaining code  has 
<E>strength</E> 1
(i.e. each coordinate contains each element of the field an equal number
of times), then it returns <M>\frac{q-1}{q}m + (n-m)</M>  
(where <M>q</M> is the size of the field and <M>m</M> is 
the length of punctured code), otherwise it returns <M>n</M>. 
This bound works for all codes.
</Description>
</ManSection>
<Index>
strength
</Index>

<Example>
gap> C:=RandomLinearCode(15,5,GF(2));
a  [15,5,?] randomly generated code over GF(2)
gap> CoveringRadius(C);
5
gap> UpperBoundCoveringRadiusStrength(C);
7
</Example>
<!--
C:=RandomLinearCode(15,5,GF(2));
CoveringRadius(C);
UpperBoundCoveringRadiusStrength(C);
-->

<ManSection>
<Func Name="UpperBoundCoveringRadiusGriesmerLike" Arg=" C "/>

<Description>
This function returns an upper bound for the covering radius
of <A>C</A>, which must be linear, in a Griesmer-like fashion. It returns

<Display>
n - \sum_{i=1}^k \left\lceil \frac{d}{q^i} \right\rceil
</Display>
</Description>
</ManSection>

<Example>
gap> C:=RandomLinearCode(15,5,GF(2));
a  [15,5,?] randomly generated code over GF(2)
gap> CoveringRadius(C);
5
gap> UpperBoundCoveringRadiusGriesmerLike(C);
9

</Example>
<!--
C:=RandomLinearCode(15,5,GF(2));
CoveringRadius(C);
UpperBoundCoveringRadiusGriesmerLike(C);
-->

<ManSection>
<Func Name="UpperBoundCoveringRadiusCyclicCode" Arg=" C "/>

<Description>
This function returns an upper bound for the covering radius
of <A>C</A>, which must be a cyclic code. It returns

<Display>
n - k + 1 - \left\lceil \frac{w(g(x))}{2} \right\rceil,
</Display>
where <M>g(x)</M> is the generator polynomial of <A>C</A>.
</Description>
</ManSection>

<Example>
gap> C:=CyclicCodes(15,GF(2))[3];
a cyclic [15,12,1..2]1..3 enumerated code over GF(2)
gap> CoveringRadius(C);
3
gap> UpperBoundCoveringRadiusCyclicCode(C);
3

</Example>
<!--
C:=CyclicCodes(15,GF(2))[3];
CoveringRadius(C);
UpperBoundCoveringRadiusCyclicCode(C);
-->


</Section>

<Section>
<Heading>
Special matrices in <Package>GUAVA</Package>
</Heading>
<Label Name="Special matrices in GUAVA"/>

This section explains functions that work with special matrices 
<Package>GUAVA</Package> needs for several codes.
<P/>
Firstly, we describe some matrix generating functions (see
<Ref Func="KrawtchoukMat" Style="Number"/>, 
<Ref Func="GrayMat" Style="Number"/>, 
<Ref Func="SylvesterMat" Style="Number"/>, 
<Ref Func="HadamardMat" Style="Number"/> and 
<Ref Func="MOLS" Style="Number"/>).
<P/>
Next we describe two functions regarding a standard form of matrices (see
<Ref Func="PutStandardForm" Style="Number"/> and 
<Ref Func="IsInStandardForm" Style="Number"/>).
<P/>
Then we describe functions that return a matrix after a manipulation (see
<Ref Func="PermutedCols" Style="Number"/>,             
<Ref Func="VerticalConversionFieldMat" Style="Number"/>   and
<Ref Func="HorizontalConversionFieldMat" Style="Number"/>).
<P/>
Finally, we describe functions that do some tests on matrices (see
<Ref Func="IsLatinSquare" Style="Number"/> and 
<Ref Func="AreMOLS" Style="Number"/>).


<ManSection>
<Func Name="KrawtchoukMat" Arg=" n q "/>

<Description>
<C>KrawtchoukMat</C> returns the <M>n+1</M> by <M>n+1</M> matrix 
<M>K=(k_{ij})</M> defined by <M>k_{ij}=K_i(j)</M> 
for <M>i,j=0,...,n</M>.  <M>K_i(j)</M> is the Krawtchouk
number 
(see <Ref Func="Krawtchouk" Style="Number"/>). 
<A>n</A> must be a positive integer and <A>q</A> a prime
power.  The Krawtchouk matrix is used in the 
<E>MacWilliams identities</E>,
defining the relation between the weight distribution of a code of length
<A>n</A>  over a field of size <A>q</A>,  and its dual code. 
Each call to <C>KrawtchoukMat</C> returns a new matrix, so it is 
safe to modify the result.
</Description>
</ManSection>

<Example>
gap> PrintArray( KrawtchoukMat( 3, 2 ) );
[ [   1,   1,   1,   1 ],
  [   3,   1,  -1,  -3 ],
  [   3,  -1,  -1,   3 ],
  [   1,  -1,   1,  -1 ] ]
gap> C := HammingCode( 3 );; a := WeightDistribution( C );
[ 1, 0, 0, 7, 7, 0, 0, 1 ]
gap> n := WordLength( C );; q := Size( LeftActingDomain( C ) );;
gap> k := Dimension( C );;
gap> q^( -k ) * KrawtchoukMat( n, q ) * a;
[ 1, 0, 0, 0, 7, 0, 0, 0 ]
gap> WeightDistribution( DualCode( C ) );
[ 1, 0, 0, 0, 7, 0, 0, 0 ] 
</Example>
<!--
PrintArray( KrawtchoukMat( 3, 2 ) );
C := HammingCode( 3 );; a := WeightDistribution( C );
n := WordLength( C );; q := Size( LeftActingDomain( C ) );;
k := Dimension( C );;
q^( -k ) * KrawtchoukMat( n, q ) * a;
WeightDistribution( DualCode( C ) );
-->


<Index>
Gary code
</Index>
<ManSection>
<Func Name="GrayMat" Arg=" n F "/>

<Description>
<C>GrayMat</C> returns a list of all different vectors (see 
GAP's <C>Vectors</C> command) of length <A>n</A> over the field <A>F</A>, 
using Gray ordering. <A>n</A> must be a positive integer.   
This order has the property that subsequent vectors
differ in exactly one coordinate. The first vector is always the null
vector. Each call to <C>GrayMat</C> returns a new matrix, so it is safe to
modify the result.
</Description>
</ManSection>

<Example>
gap> GrayMat(3);
[ [ 0*Z(2), 0*Z(2), 0*Z(2) ], [ 0*Z(2), 0*Z(2), Z(2)^0 ],
  [ 0*Z(2), Z(2)^0, Z(2)^0 ], [ 0*Z(2), Z(2)^0, 0*Z(2) ],
  [ Z(2)^0, Z(2)^0, 0*Z(2) ], [ Z(2)^0, Z(2)^0, Z(2)^0 ],
  [ Z(2)^0, 0*Z(2), Z(2)^0 ], [ Z(2)^0, 0*Z(2), 0*Z(2) ] ]
gap> G := GrayMat( 4, GF(4) );; Length(G);
256          # the length of a GrayMat is always q^n
gap> G[101] - G[100];
[ 0*Z(2), 0*Z(2), Z(2)^0, 0*Z(2) ] 
</Example>
<!--
GrayMat(3);
G := GrayMat( 4, GF(4) );; Length(G);
G[101] - G[100];
-->

<ManSection>
<Func Name="SylvesterMat" Arg=" n "/>

<Description>
<C>SylvesterMat</C> returns the <M>n\times n</M> 
Sylvester matrix of order <A>n</A>. This
is a special case of the Hadamard matrices (see 
<Ref Func="HadamardMat" Style="Number"/>). For this
construction, <A>n</A> must be a power of <M>2</M>. Each 
call to <C>SylvesterMat</C> returns a new matrix, so it is 
safe to modify the result.
</Description>
</ManSection>

<Example>
gap> PrintArray(SylvesterMat(2));
[ [   1,   1 ],
  [   1,  -1 ] ]
gap> PrintArray( SylvesterMat(4) );
[ [   1,   1,   1,   1 ],
  [   1,  -1,   1,  -1 ],
  [   1,   1,  -1,  -1 ],
  [   1,  -1,  -1,   1 ] ] 
</Example>

<Index>
Hadamard matrix
</Index>

<ManSection>
<Func Name="HadamardMat" Arg=" n "/>

<Description>
<C>HadamardMat</C> returns a Hadamard matrix of order <A>n</A>. 
This is an <M>n\times n</M> matrix with the property that 
the matrix multiplied by its transpose
returns <A>n</A> times the identity matrix. This is only possible for 
<M>n=1, n=2</M> or in cases where <A>n</A> is a multiple of <M>4</M>. 
If the matrix does not exist or is not known (as of 1998), 
<C>HadamardMat</C> returns an error. A large number of
construction methods is known to create these matrices for different
orders. <C>HadamardMat</C> makes use of two construction methods (the 
Paley Type I and II constructions, and the Sylvester construction -- see 
<Ref Func="SylvesterMat" Style="Number"/>). These methods cover
most of the possible Hadamard matrices, although some special algorithms
have not been implemented yet. The following orders less than 
<M>100</M> do not yet have an implementation for a Hadamard 
matrix in <Package>GUAVA</Package>: <M>52, 92</M>.
</Description>
</ManSection>

<Example>
gap> C := HadamardMat(8);; PrintArray(C);
[ [   1,   1,   1,   1,   1,   1,   1,   1 ],
  [   1,  -1,   1,  -1,   1,  -1,   1,  -1 ],
  [   1,   1,  -1,  -1,   1,   1,  -1,  -1 ],
  [   1,  -1,  -1,   1,   1,  -1,  -1,   1 ],
  [   1,   1,   1,   1,  -1,  -1,  -1,  -1 ],
  [   1,  -1,   1,  -1,  -1,   1,  -1,   1 ],
  [   1,   1,  -1,  -1,  -1,  -1,   1,   1 ],
  [   1,  -1,  -1,   1,  -1,   1,   1,  -1 ] ]
gap> C * TransposedMat(C) = 8 * IdentityMat( 8, 8 );
true 
</Example>


<ManSection>
<Func Name="VandermondeMat" Arg=" X a "/>

<Description>
The function <C>VandermondeMat</C> returns the 
<M>(a+1)\times n</M> matrix of powers <M>x_i^j</M> where 
<A>X</A> is a list of elements of a field,
<M>X=\{ x_1,...,x_n\}</M>, and <A>a</A> is a
non-negative integer. 
</Description>
</ManSection>

<Example>
gap> M:=VandermondeMat([Z(5),Z(5)^2,Z(5)^0,Z(5)^3],2);
[ [ Z(5)^0, Z(5), Z(5)^2 ], [ Z(5)^0, Z(5)^2, Z(5)^0 ],
  [ Z(5)^0, Z(5)^0, Z(5)^0 ], [ Z(5)^0, Z(5)^3, Z(5)^2 ] ]
gap> Display(M);
 1 2 4
 1 4 1
 1 1 1
 1 3 4
</Example>
<!--
M:=VandermondeMat([Z(5),Z(5)^2,Z(5)^0,Z(5)^3],2);
Display(M);
-->

<Index>
standard form
</Index>

<ManSection>
<Func Name="PutStandardForm" Arg=" M [idleft] "/>

<Description>
We say that a <M>k\times n</M> matrix is in <E>standard form</E>
if it is equal to the block matrix <M>(I\ |\ A)</M>, for 
some <M>k\times (n-k)</M> matrix <M>A</M> and where
<M>I</M> is the <M>k\times k</M> identity matrix.
It follows from a basis result in linear algebra that,
after a possible permutation of the columns,
using elementary row operations, every matrix can be 
reduced to standard form.
<C>PutStandardForm</C> puts a matrix <A>M</A> in standard form, 
and returns the permutation needed to do so. <A>idleft</A> 
is a boolean that sets the position of the identity matrix in 
<A>M</A>. (The default for <A>idleft</A> is `true'.)
If <A>idleft</A> is set to `true', the identity
matrix is put on the left side of <A>M</A>. 
Otherwise, it is put at the right side. 
(This option is useful when putting a check matrix of a code
into standard form.)
The function <C>BaseMat</C> also returns a similar standard form, but does not
apply column permutations. The rows of the matrix still span the same
vector space after <C>BaseMat</C>,  but after calling 
<C>PutStandardForm</C>, this is not necessarily true.
</Description>
</ManSection>

<Example>
gap> M := Z(2)*[[1,0,0,1],[0,0,1,1]];; PrintArray(M);
[ [    Z(2),  0*Z(2),  0*Z(2),    Z(2) ],
  [  0*Z(2),  0*Z(2),    Z(2),    Z(2) ] ]
gap> PutStandardForm(M);                   # identity at the left side
(2,3)
gap> PrintArray(M);
[ [    Z(2),  0*Z(2),  0*Z(2),    Z(2) ],
  [  0*Z(2),    Z(2),  0*Z(2),    Z(2) ] ]
gap> PutStandardForm(M, false);            # identity at the right side
(1,4,3)
gap> PrintArray(M);
[ [  0*Z(2),    Z(2),    Z(2),  0*Z(2) ],
  [  0*Z(2),    Z(2),  0*Z(2),    Z(2) ] ]
gap> C := BestKnownLinearCode( 23, 12, GF(2) );
a linear [23,12,7]3 punctured code
gap> G:=MutableCopyMat(GeneratorMat(C));;
gap> PutStandardForm(G);
()
gap> Display(G);
 1 . . . . . . . . . . . 1 . 1 . 1 1 1 . . . 1
 . 1 . . . . . . . . . . 1 1 1 1 1 . . 1 . . .
 . . 1 . . . . . . . . . 1 1 . 1 . . 1 . 1 . 1
 . . . 1 . . . . . . . . 1 1 . . . 1 1 1 . 1 .
 . . . . 1 . . . . . . . 1 1 . . 1 1 . 1 1 . 1
 . . . . . 1 . . . . . . . 1 1 . . 1 1 . 1 1 1
 . . . . . . 1 . . . . . . . 1 1 . . 1 1 . 1 1
 . . . . . . . 1 . . . . 1 . 1 1 . 1 1 1 1 . .
 . . . . . . . . 1 . . . . 1 . 1 1 . 1 1 1 1 .
 . . . . . . . . . 1 . . . . 1 . 1 1 . 1 1 1 .
 . . . . . . . . . . 1 . 1 . 1 1 1 . . . 1 1 1
 . . . . . . . . . . . 1 . 1 . 1 1 1 . . . 1 1

</Example>

<ManSection>
<Func Name="IsInStandardForm" Arg=" M [idleft] "/>

<Description>
<C>IsInStandardForm</C> determines if <A>M</A> is in standard form. 
<A>idleft</A> is a boolean that indicates the position of the 
identity matrix in <A>M</A>, as in <C>PutStandardForm</C> (see
<Ref Func="PutStandardForm" Style="Number"/>).
<C>IsInStandardForm</C> checks if the identity matrix is
at the left side of <A>M</A>, otherwise if it is at the 
right side. The elements of <A>M</A> may be elements  of
any field.  
</Description>
</ManSection>

<Example>
gap> IsInStandardForm(IdentityMat(7, GF(2)));
true
gap> IsInStandardForm([[1, 1, 0], [1, 0, 1]], false);
true
gap> IsInStandardForm([[1, 3, 2, 7]]);
true
gap> IsInStandardForm(HadamardMat(4));
false 
</Example>


<ManSection>
<Func Name="PermutedCols" Arg=" M P "/>

<Description>
<C>PermutedCols</C> returns a matrix <A>M</A> with a permutation 
<A>P</A> applied to its columns.
</Description>
</ManSection>

<Example>
gap> M := [[1,2,3,4],[1,2,3,4]];; PrintArray(M);
[ [  1,  2,  3,  4 ],
  [  1,  2,  3,  4 ] ]
gap> PrintArray(PermutedCols(M, (1,2,3)));
[ [  3,  1,  2,  4 ],
  [  3,  1,  2,  4 ] ] 
</Example>

<ManSection>
<Func Name="VerticalConversionFieldMat" Arg=" M F "/>

<Description>
<C>VerticalConversionFieldMat</C> returns the matrix 
<A>M</A> with its elements converted from a field 
<M>F=GF(q^m)</M>, <M>q</M> prime, to a field <M>GF(q)</M>. Each
element is replaced by its representation over the latter field, placed
vertically in the matrix, using the <M>GF(p)</M>-vector space
isomorphism 

<Display>

[...] : GF(q)\rightarrow GF(p)^m,
</Display>
with <M>q=p^m</M>. 
<P/>
If <A>M</A> is a <M>k</M> by <M>n</M> matrix, the result is 
a <M>k\cdot m \times n</M> matrix,
since each element of <M>GF(q^m)</M> can be represented  
in <M>GF(q)</M> using <M>m</M> elements.
</Description>
</ManSection>

<Example>
gap> M := Z(9)*[[1,2],[2,1]];; PrintArray(M);
[ [    Z(3^2),  Z(3^2)^5 ],
  [  Z(3^2)^5,    Z(3^2) ] ]
gap> DefaultField( Flat(M) );
GF(3^2)
gap> VCFM := VerticalConversionFieldMat( M, GF(9) );; PrintArray(VCFM);
[ [  0*Z(3),  0*Z(3) ],
  [  Z(3)^0,    Z(3) ],
  [  0*Z(3),  0*Z(3) ],
  [    Z(3),  Z(3)^0 ] ]
gap> DefaultField( Flat(VCFM) );
GF(3) 
</Example>

A similar function is <C>HorizontalConversionFieldMat</C> (see
<Ref Func="HorizontalConversionFieldMat" Style="Number"/>).

<ManSection>
<Func Name="HorizontalConversionFieldMat" Arg=" M F "/>

<Description>
<C>HorizontalConversionFieldMat</C> returns the matrix <A>M</A> 
with its elements converted from a field <M>F=GF(q^m)</M>, 
<M>q</M> prime, to a field <M>GF(q)</M>. 
Each element is replaced by its representation over the 
latter field, placed horizontally in the matrix.
<P/>
If <A>M</A> is a <M>k \times n</M> matrix, the result is a 
<M>k\times m\times n\cdot m</M> matrix. 
The new word length of the resulting code is equal to 
<M>n\cdot m</M>, because each element of <M>GF(q^m)</M> 
can be represented in <M>GF(q)</M> using <M>m</M> elements. 
The new dimension is equal to <M>k\times m</M> 
because the new matrix should be a basis for the same number 
of vectors as the old one.
<P/>
<C>ConversionFieldCode</C> uses horizontal conversion to 
convert a code (see
<Ref Func="ConversionFieldCode" Style="Number"/>).
</Description>
</ManSection>

<Example>
gap> M := Z(9)*[[1,2],[2,1]];; PrintArray(M);
[ [    Z(3^2),  Z(3^2)^5 ],
  [  Z(3^2)^5,    Z(3^2) ] ]
gap> DefaultField( Flat(M) );
GF(3^2)
gap> HCFM := HorizontalConversionFieldMat(M, GF(9));; PrintArray(HCFM);
[ [  0*Z(3),  Z(3)^0,  0*Z(3),    Z(3) ],
  [  Z(3)^0,  Z(3)^0,    Z(3),    Z(3) ],
  [  0*Z(3),    Z(3),  0*Z(3),  Z(3)^0 ],
  [    Z(3),    Z(3),  Z(3)^0,  Z(3)^0 ] ]
gap> DefaultField( Flat(HCFM) );
GF(3) 
</Example>

A similar function is <C>VerticalConversionFieldMat</C> (see
<Ref Func="VerticalConversionFieldMat" Style="Number"/>).

<Index>
mutually orthogonal Latin squares
</Index>
<Index>
Latin square
</Index>

<ManSection>
<Func Name="MOLS" Arg=" q [n] "/>

<Description>
<C>MOLS</C> returns a list of <A>n</A> <E>Mutually Orthogonal 
Latin Squares</E> (MOLS). A <E>Latin square</E> 
of order <A>q</A> is a <M>q\times q</M> matrix whose
entries are from a set <M>F_{q}</M> of <A>q</A> 
distinct symbols (<Package>GUAVA</Package> uses the 
integers from <M>0</M> to <A>q</A>) such that each row 
and each column of the matrix contains each symbol exactly once.
<P/>
A set of Latin squares is a set of MOLS if and only if for each pair of
Latin squares in this set, every ordered pair of elements that are in the
same position in these matrices occurs exactly once.
<P/>
<A>n</A> must be less than <A>q</A>.  If <A>n</A> is omitted, 
two MOLS are returned. If <A>q</A> is not a prime power,  
at most <M>2</M> MOLS can be created. For all values
of <A>q</A> with  <M>q > 2</M> and <M>q \neq 6</M>, 
a list of MOLS can be constructed. However, 
<Package>GUAVA</Package> does not yet construct MOLS for 
<M>q\equiv 2 \pmod 4</M>.  If it is not possible to construct 
<A>n</A> MOLS,  the function returns `false'.
<P/>
MOLS are used to create <A>q</A>-ary codes (see 
<Ref Func="MOLSCode" Style="Number"/>).
</Description>
</ManSection>

<Example>
gap> M := MOLS( 4, 3 );;PrintArray( M[1] );
[ [  0,  1,  2,  3 ],
  [  1,  0,  3,  2 ],
  [  2,  3,  0,  1 ],
  [  3,  2,  1,  0 ] ]
gap> PrintArray( M[2] );
[ [  0,  2,  3,  1 ],
  [  1,  3,  2,  0 ],
  [  2,  0,  1,  3 ],
  [  3,  1,  0,  2 ] ]
gap> PrintArray( M[3] );
[ [  0,  3,  1,  2 ],
  [  1,  2,  0,  3 ],
  [  2,  1,  3,  0 ],
  [  3,  0,  2,  1 ] ]
gap> MOLS( 12, 3 );
false 
</Example>

<ManSection>
<Func Name="IsLatinSquare" Arg=" M "/>

<Description>
<C>IsLatinSquare</C> determines if a matrix <A>M</A> is a 
Latin square. For a Latin square of size <M>n\times n</M>,  
each row and each column contains all the integers 
<M>1,\dots,n</M> exactly once.
</Description>
</ManSection>

<Example>
gap> IsLatinSquare([[1,2],[2,1]]);
true
gap> IsLatinSquare([[1,2,3],[2,3,1],[1,3,2]]);
false 
</Example>

<ManSection>
<Func Name="AreMOLS" Arg=" L "/>

<Description>
<C>AreMOLS</C> determines if <A>L</A> is a list of mutually 
orthogonal Latin squares (MOLS). For each pair of 
Latin squares in this list, the function checks if each ordered 
pair of elements that are in the same position in
these matrices occurs exactly once. The function <C>MOLS</C> 
creates MOLS (see <Ref Func="MOLS" Style="Number"/>).
</Description>
</ManSection>

<Example>
gap> M := MOLS(4,2);
[ [ [ 0, 1, 2, 3 ], [ 1, 0, 3, 2 ], [ 2, 3, 0, 1 ], [ 3, 2, 1, 0 ] ],
  [ [ 0, 2, 3, 1 ], [ 1, 3, 2, 0 ], [ 2, 0, 1, 3 ], [ 3, 1, 0, 2 ] ] ]
gap> AreMOLS(M);
true 
</Example>


</Section>

<Section>
<Heading>
Some functions related to the norm of a code
</Heading>
<Label Name="Some functions related to the norm of a code"/>

In this section, some functions that can be used to compute the norm of a
code and to decide upon its normality are discussed.
Typically, these are applied to binary linear codes.
The definitions of this section were introduced in
Graham and Sloane <Cite Key="GS85"/>.

<ManSection>
<Func Name="CoordinateNorm" Arg=" C coord "/>

<Description>
<C>CoordinateNorm</C> returns the norm of <A>C</A> with respect to
coordinate <A>coord</A>. If 
<M>C_a = \{ c \in C \ |\ c_{coord} = a \}</M>,
then the norm of <A>C</A> with respect to <A>coord</A> is
defined as

<Display>
\max_{v \in GF(q)^n} \sum_{a=1}^q d(x,C_a),
</Display>
with the convention that <M>d(x,C_a) = n</M> 
if <M>C_a</M> is empty.
</Description>
</ManSection>

<Example>
gap> CoordinateNorm( HammingCode( 3, GF(2) ), 3 );
3 
</Example>

<Index>
norm of a code
</Index>

<ManSection>
<Func Name="CodeNorm" Arg=" C "/>

<Description>
<C>CodeNorm</C> returns the norm of <A>C</A>. 
The <E>norm</E> of a code is defined as
the minimum of the norms for the respective coordinates of the code.  In
effect, for each coordinate <C>CoordinateNorm</C> 
is called, and the minimum
of the calculated numbers is returned.
</Description>
</ManSection>

<Example>
gap> CodeNorm( HammingCode( 3, GF(2) ) );
3 
</Example>

<Index>
acceptable coordinate
</Index>

<ManSection>
<Func Name="IsCoordinateAcceptable" Arg=" C coord "/>

<Description>
<C>IsCoordinateAcceptable</C> returns `true' if
coordinate <A>coord</A> of <A>C</A> is acceptable.
A coordinate is called <E>acceptable</E> if the norm of
the code with respect to that coordinate is
not more than two times the covering radius of
the code plus one.
</Description>
</ManSection>

<Example>
gap> IsCoordinateAcceptable( HammingCode( 3, GF(2) ), 3 );
true 
</Example>

<Index>
acceptable coordinate
</Index>

<ManSection>
<Func Name="GeneralizedCodeNorm" Arg=" C subcode1 subscode2 ... subcodek "/>

<Description>
<C>GeneralizedCodeNorm</C> returns the <A>k</A>-norm of <A>C</A> 
with respect to <A>k</A> subcodes.
</Description>
</ManSection>

<Example>
gap> c := RepetitionCode( 7, GF(2) );;
gap> ham := HammingCode( 3, GF(2) );;
gap> d := EvenWeightSubcode( ham );;
gap> e := ConstantWeightSubcode( ham, 3 );;
gap> GeneralizedCodeNorm( ham, c, d, e );
4 
</Example>


<Index>
normal code
</Index>

<ManSection>
<Func Name="IsNormalCode" Arg=" C "/>

<Description>
<C>IsNormalCode</C> returns `true' if <A>C</A> is normal. 
A code is called <E>normal</E> if the norm of the code is not 
more than two times  the covering radius of the code plus one. 
Almost all codes are  normal,  however  some
(non-linear) abnormal codes have been found.
<P/>
Often, it is difficult to find out whether a code is normal,  because  it
involves computing the covering radius. However, 
<C>IsNormalCode</C> uses much
information  from the literature (in particular,
<Cite Key="GS85"/>) about normality for certain code
parameters.
</Description>
</ManSection>

<Example>
gap> IsNormalCode( HammingCode( 3, GF(2) ) );
true 
</Example>

</Section>

<Section>
<Heading>
Miscellaneous functions
</Heading>
<Label Name="Miscellaneous functions"/>

In this section we describe several vector space functions 
<Package>GUAVA</Package> uses for
constructing codes or performing calculations with codes.
<P/>
In this section, some new miscellaneous functions are described,
including weight enumerators, the MacWilliams-transform and 
affinity and almost affinity of codes.

<Index>
weight enumerator polynomial
</Index>

<ManSection>
<Func Name="CodeWeightEnumerator" Arg=" C "/>

<Description>
<C>CodeWeightEnumerator</C> returns a polynomial of the following form:

<Display>
f(x) = \sum_{i=0}^{n} A_i x^i,
</Display>
where <M>A_i</M> is the number of codewords in <A>C</A> with weight 
<M>i</M>.
</Description>
</ManSection>

<Example>
gap> CodeWeightEnumerator( ElementsCode( [ [ 0,0,0 ], [ 0,0,1 ],
> [ 0,1,1 ], [ 1,1,1 ] ], GF(2) ) );
x^3 + x^2 + x + 1
gap> CodeWeightEnumerator( HammingCode( 3, GF(2) ) );
x^7 + 7*x^4 + 7*x^3 + 1 
</Example>

<ManSection>
<Func Name="CodeDistanceEnumerator" Arg=" C w "/>

<Description>
<C>CodeDistanceEnumerator</C> returns a polynomial of the following form:

<Display>
f(x) = \sum_{i=0}^{n} B_i x^i,
</Display>
where <M>B_i</M> is the number of codewords with distance 
<M>i</M> to <A>w</A>.
<P/>
If <A>w</A> is a codeword, then <C>CodeDistanceEnumerator</C> returns the
same polynomial as <C>CodeWeightEnumerator</C>.
</Description>
</ManSection>

<Example>
gap> CodeDistanceEnumerator( HammingCode( 3, GF(2) ),[0,0,0,0,0,0,1] );
x^6 + 3*x^5 + 4*x^4 + 4*x^3 + 3*x^2 + x
gap> CodeDistanceEnumerator( HammingCode( 3, GF(2) ),[1,1,1,1,1,1,1] );
x^7 + 7*x^4 + 7*x^3 + 1 # `[1,1,1,1,1,1,1]' $\in$ `HammingCode( 3, GF(2 ) )'
</Example>

<Index>
MacWilliams transform
</Index>


<ManSection>
<Func Name="CodeMacWilliamsTransform" Arg=" C "/>

<Description>
<C>CodeMacWilliamsTransform</C> returns a polynomial of the following form:

<Display>
f(x) = \sum_{i=0}^{n} C_i x^i,
</Display>
where <M>C_i</M> is the number of codewords with weight <M>i</M> 
in the <E>dual</E> code of <A>C</A>.
</Description>
</ManSection>

<Example>
gap> CodeMacWilliamsTransform( HammingCode( 3, GF(2) ) );
7*x^4 + 1 
</Example>


<Index>
density of a code
</Index>
<ManSection>
<Func Name="CodeDensity" Arg=" C "/>

<Description>
<C>CodeDensity</C> returns the <E>density</E> of <A>C</A>.
The density of a code is defined as

<Display>
\frac{M \cdot V_q(n,t)}{q^n},
</Display>
where <M>M</M> is the size of the code, 
<M>V_q(n,t)</M> is the size of a sphere of
radius <M>t</M> in <M>GF(q^n)</M> (which may be 
computed using <C>SphereContent</C>), 
<M>t</M> is the covering radius of the code and 
<M>n</M> is the length of the code.
</Description>
</ManSection>

<Example>
gap> CodeDensity( HammingCode( 3, GF(2) ) );
1
gap> CodeDensity( ReedMullerCode( 1, 4 ) );
14893/2048 
</Example>

<Index>
perfect code
</Index>
<ManSection>
<Func Name="SphereContent" Arg=" n t F "/>

<Description>
<C>SphereContent</C> returns the  content of a ball of radius 
<A>t</A> around an arbitrary element of the vectorspace 
<M>F^n</M>.  This is the cardinality of the set of all elements 
of <M>F^n</M> that are at distance (see
<Ref Func="DistanceCodeword" Style="Number"/>
less than or equal to <A>t</A> from  an  element of <M>F^n</M>.
<P/>
In the context of codes, the function is used to  determine if a code is
perfect. A code is <E>perfect</E> if spheres of radius 
<M>t</M> around all codewords
partition the whole ambient vector space, where 
<E>t</E> is the number of errors the code can correct.
</Description>
</ManSection>

<Example>
gap> SphereContent( 15, 0, GF(2) );
1    # Only one word with distance 0, which is the word itself
gap> SphereContent( 11, 3, GF(4) );
4984
gap> C := HammingCode(5);
a linear [31,26,3]1 Hamming (5,2) code over GF(2)
#the minimum distance is 3, so the code can correct one error
gap> ( SphereContent( 31, 1, GF(2) ) * Size(C) ) = 2 ^ 31;
true 
</Example>

<ManSection>
<Func Name="Krawtchouk" Arg=" k i n q "/>

<Description>
<C>Krawtchouk</C> returns the Krawtchouk number 
<M>K_{k}(i)</M>.  <A>q</A> must be a prime power, <A>n</A> 
must be a positive integer,  <A>k</A> must be a non-negative
integer less then or equal to <A>n</A> and <A>i</A> can be any  
integer. (See
<Ref Func="KrawtchoukMat" Style="Number"/>). 
This number is the value at <M>x=i</M> of the polynomial 

<Display>
K_k^{n,q}(x)
=\sum_{j=0}^n (-1)^j(q-1)^{k-j}b(x,j)b(n-x,k-j),
</Display>
where $b(v,u)=u!/(v!(v-u)!)$ is the binomial coefficient if $u,v$ are
integers. For more properties of these polynomials,
see <Cite Key="MS83"/>.
</Description>
</ManSection>

<Example>
gap> Krawtchouk( 2, 0, 3, 2);
3 
</Example>

<ManSection>
<Func Name="PrimitiveUnityRoot" Arg=" F n "/>

<Description>
<C>PrimitiveUnityRoot</C> returns a primitive <A>n</A>-th  
root of unity in an extension field of <A>F</A>. 
This is a finite field element <M>a</M> with the
property <M>a^n=1</M> in <A>F</A>, and <A>n</A> 
is the smallest integer such that this equality holds.
</Description>
</ManSection>

<Example>
gap> PrimitiveUnityRoot( GF(2), 15 );
Z(2^4)
gap> last^15;
Z(2)^0
gap> PrimitiveUnityRoot( GF(8), 21 );
Z(2^6)^3 
</Example>

<ManSection>
<Func Name="PrimitivePolynomialsNr" Arg=" n F "/>

<Description>
<C>PrimitivePolynomialsNr</C> returns the number of irreducible 
polynomials over <M>F=GF(q)</M> of degree <A>n</A> 
with (maximum) period <M>q^n-1</M>.
(According to a theorem of S. Golomb, this is
<M>\phi(p^n-1)/n</M>.)
<P/>
See also the GAP function <C>RandomPrimitivePolynomial</C>, 
<Ref Func="RandomPrimitivePolynomial" Style="Number"/>.
</Description>
</ManSection>

<Example>
gap> PrimitivePolynomialsNr(3,4);
12

</Example>


<ManSection>
<Func Name="IrreduciblePolynomialsNr" Arg=" n F "/>

<Description>
<C>PrimitivePolynomialsNr</C> returns the number of irreducible 
polynomials over <M>F=GF(q)</M> of degree <A>n</A>.
</Description>
</ManSection>

<Example>
gap> IrreduciblePolynomialsNr(3,4);
20

</Example>


<ManSection>
<Func Name="MatrixRepresentationOfElement" Arg=" a F "/>

<Description>
Here <A>F</A> is either a finite extension of
the ``base field'' <M>GF(p)</M> or of the rationals <M>{\mathbb{Q}}</M>,
and <M>a\in F</M>. 
The command <C>MatrixRepresentationOfElement</C> returns a matrix 
representation of <A>a</A> over the base field.  
<P/>
If the element <A>a</A> is defined over the base field then it
returns the corresponding <M>1\times 1</M> matrix.
</Description>
</ManSection>

<Example>
gap> a:=Random(GF(4));
0*Z(2)
gap> M:=MatrixRepresentationOfElement(a,GF(4));; Display(M);
 .
gap> a:=Random(GF(4));
Z(2^2)
gap> M:=MatrixRepresentationOfElement(a,GF(4));; Display(M);
 . 1
 1 1
gap>

</Example>
<!--
a:=Random(GF(4));
M:=MatrixRepresentationOfElement(a,GF(4));; Display(M);
a:=Random(GF(4));
M:=MatrixRepresentationOfElement(a,GF(4));; Display(M);
-->

<Index>
reciprocal polynomial
</Index>

<ManSection>
<Func Name="ReciprocalPolynomial" Arg=" P "/>

<Description>
<C>ReciprocalPolynomial</C> returns the <E>reciprocal</E> of 
polynomial <A>P</A>. This is a polynomial with coefficients of 
<A>P</A> in the reverse order. So if
<M>P=a_0 + a_1 X +  ... + a_{n}  X^{n}</M>, 
the reciprocal polynomial is
<M>P'=a_{n} + a_{n-1} X + ... + a_0 X^{n}</M>.
<P/>
This command can also be called using the
syntax <C>ReciprocalPolynomial( P , n )</C>.
In this form, the number of coefficients of <A>P</A> is 
assumed to be less than or equal to <M>n+1</M>  
(with zero coefficients added in the highest
degrees, if necessary). 
Therefore, the reciprocal polynomial also has degree
<M>n+1</M>.
</Description>
</ManSection>

<Example>
gap> P := UnivariatePolynomial( GF(3), Z(3)^0 * [1,0,1,2] );
Z(3)^0+x_1^2-x_1^3
gap> RecP := ReciprocalPolynomial( P );
-Z(3)^0+x_1+x_1^3
gap> ReciprocalPolynomial( RecP ) = P;
true 
gap> P := UnivariatePolynomial( GF(3), Z(3)^0 * [1,0,1,2] );
Z(3)^0+x_1^2-x_1^3
gap> ReciprocalPolynomial( P, 6 );
-x_1^3+x_1^4+x_1^6
</Example>
<!--
P := UnivariatePolynomial( GF(3), Z(3)^0 * [1,0,1,2] );
RecP := ReciprocalPolynomial( P );
ReciprocalPolynomial( RecP ) = P;
P := UnivariatePolynomial( GF(3), Z(3)^0 * [1,0,1,2] );
ReciprocalPolynomial( P, 6 );
-->

<ManSection>
<Func Name="CyclotomicCosets" Arg=" q n "/>

<Description>
<C>CyclotomicCosets</C> returns the cyclotomic cosets of 
<M>q \pmod n</M>. <A>q</A> and <A>n</A> must be relatively prime. 
Each of the elements of the returned list is a list of integers 
that belong to one cyclotomic coset.  
A <M>q</M>-cyclotomic coset of <M>s \pmod n</M> is a set of the
form <M>\{s,sq,sq^2,...,sq^{r-1}\}</M>, where <M>r</M> is the 
smallest positive integer such that 
<M>sq^r-s</M> is <M>0 \pmod n</M>. In other words, each
coset contains all multiplications of the coset representative 
by <M>q \pmod n</M>. 
The coset representative is the smallest integer that isn't
in the previous cosets.
</Description>
</ManSection>

<Example>
gap> CyclotomicCosets( 2, 15 );
[ [ 0 ], [ 1, 2, 4, 8 ], [ 3, 6, 12, 9 ], [ 5, 10 ],
  [ 7, 14, 13, 11 ] ]
gap> CyclotomicCosets( 7, 6 );
[ [ 0 ], [ 1 ], [ 2 ], [ 3 ], [ 4 ], [ 5 ] ] 
</Example>

<ManSection>
<Func Name="WeightHistogram" Arg=" C [h] "/>

<Description>
The function <C>WeightHistogram</C> plots a histogram  of weights in code
<A>C</A>. The maximum length of a column is <A>h</A>. 
Default value for <A>h</A> is <M>1/3</M> of the size of the  
screen. The number that appears at the top of
the histogram is the maximum value of the list of weights.
</Description>
</ManSection>

<Example>
gap> H := HammingCode(2, GF(5));
a linear [6,4,3]1 Hamming (2,5) code over GF(5)
gap> WeightDistribution(H);
[ 1, 0, 0, 80, 120, 264, 160 ]
gap> WeightHistogram(H);
264----------------
               *
               *
               *
               *
               *  *
            *  *  *
         *  *  *  *
         *  *  *  *
+--------+--+--+--+--
0  1  2  3  4  5  6 
</Example>
<!--
H := HammingCode(2, GF(5));
WeightDistribution(H);
WeightHistogram(H);
-->


<ManSection>
<Func Name="MultiplicityInList" Arg ="L, a"/>

<Description>
This is a very simple list command which 
returns how many times a occurs in L.
It returns 0 if a is not in L.
(The GAP command <C>Collected</C> does not quite
handle this "extreme" case.) 

</Description>
</ManSection>
<Example>
gap> L:=[1,2,3,4,3,2,1,5,4,3,2,1];;
gap> MultiplicityInList(L,1);
3
gap> MultiplicityInList(L,6);
0
</Example>
<!--
L:=[1,2,3,4,3,2,1,5,4,3,2,1];;
MultiplicityInList(L,1);
MultiplicityInList(L,6);
-->

<ManSection>
<Func Name="MostCommonInList" Arg =" L "/>

<Description>

Input: a list L
<P/>
Output: an a in L which occurs at least as much as any other in L

</Description>
</ManSection>
<Example>
gap> L:=[1,2,3,4,3,2,1,5,4,3,2,1];;
gap> MostCommonInList(L);
1
</Example>
<!--
L:=[1,2,3,4,3,2,1,5,4,3,2,1];;
MostCommonInList(L);
-->

<ManSection>
<Func Name="RotateList" Arg =" L "/>

<Description>

Input: a list L
<P/>
Output: a list L' which is the
cyclic rotation of L (to the right)


</Description>
</ManSection>
<Example>
gap> L:=[1,2,3,4];;
gap> RotateList(L);
[2,3,4,1]
</Example>
<!--
L:=[1,2,3,4];;
RotateList(L);
-->

<ManSection>
<Func Name="CirculantMatrix" Arg =" k L "/>

<Description>
Input: integer k, a list L of length n
<P/>
Output: kxn matrix whose rows are cyclic rotations of the list L

</Description>
</ManSection>
<Example>
gap> k:=3; L:=[1,2,3,4];;
gap> M:=CirculantMatrix(k,L);;
gap> Display(M);
</Example>
<!--
k:=3; L:=[1,2,3,4];;
M:=CirculantMatrix(k,L);;
Display(M);
-->


</Section>

<Section>
<Heading>
Miscellaneous polynomial functions
</Heading>
<Label Name="Miscellaneous polynomial functions"/>

In this section we describe several multivariate polynomial
GAP functions <Package>GUAVA</Package> uses for
constructing codes or performing calculations with codes.

<ManSection>

<Func Name="MatrixTransformationOnMultivariatePolynomial " Arg ="A,f,R "/>

<Description>
<A>A</A> is an <M>n\times n</M> matrix with entries in a field <M>F</M>,
<A>R</A> is a polynomial ring of <M>n</M> variables,
say <M>F[x_1,...,x_n]</M>, and <A>f</A> is a polynomial in <A>R</A>.
Returns the composition <M>f\circ A</M>.

</Description>
</ManSection>

<ManSection>
<Func Name="DegreeMultivariatePolynomial" Arg ="f, R"/>

<Description>
This command takes two arguments,
<A>f</A>, a multivariate polynomial,
and <A>R</A> a polynomial ring over
a field <M>F</M> containing <A>f</A>, say
<M>R=F[x_1,x_2,...,x_n]</M>.
The output is simply the maximum degrees of all the
monomials occurring in <A>f</A>.
<P/>
This command can be used to compute the degree of an
affine plane curve.

</Description>
</ManSection>

<Example>
gap> F:=GF(11);;
gap> R2:=PolynomialRing(F,2);
PolynomialRing(..., [ x_1, x_2 ])
gap> vars:=IndeterminatesOfPolynomialRing(R2);;
gap> x:=vars[1];; y:=vars[2];;
gap> poly:=y^2-x*(x^2-1);;
gap> DegreeMultivariatePolynomial(poly,R2);
3

</Example>
<!--
F:=GF(11);;
R2:=PolynomialRing(F,2);
vars:=IndeterminatesOfPolynomialRing(R2);;
x:=vars[1];; y:=vars[2];;
poly:=y^2-x*(x^2-1);;
DegreeMultivariatePolynomial(poly,R2);

-->

<ManSection>

<Func Name="DegreesMultivariatePolynomial" Arg ="f, R"/>

<Description>
Returns a list of information about the 
multivariate polynomial <A>f</A>. Nice for other
programs but mostly unreadable by GAP users.


</Description>
</ManSection>

<Example>
gap> F:=GF(11);;
gap> R2:=PolynomialRing(F,2);
PolynomialRing(..., [ x_1, x_2 ])
gap> vars:=IndeterminatesOfPolynomialRing(R2);;
gap> x:=vars[1];; y:=vars[2];;
gap> poly:=y^2-x*(x^2-1);;
gap> DegreesMultivariatePolynomial(poly,R2);
[ [ [ x_1, x_1, 1 ], [ x_1, x_2, 0 ] ], [ [ x_2^2, x_1, 0 ], [ x_2^2, x_2, 2 ] ],
  [ [ x_1^3, x_1, 3 ], [ x_1^3, x_2, 0 ] ] ]
gap>

</Example>
<!--
F:=GF(11);;
R2:=PolynomialRing(F,2);
vars:=IndeterminatesOfPolynomialRing(R2);;
x:=vars[1];; y:=vars[2];;
poly:=y^2-x*(x^2-1);;
DegreesMultivariatePolynomial(poly,R2);

-->

<ManSection>
<Func Name="CoefficientMultivariatePolynomial" Arg ="f, var, power, R"/>

<Description>
The command <C>CoefficientMultivariatePolynomial</C>
takes four arguments: a multivariant polynomial 
<A>f</A>, a variable name <A>var</A>, an integer
<A>power</A>, and a polynomial ring <A>R</A> containing <A>f</A>.
For example, if <A>f</A> is a multivariate polynomial in 
<M>R</M> = <M>F</M>[<M>x_1,x_2,...,x_n</M>] then <A>var</A> must be
one of the <M>x_i</M>.
The output is the coefficient of <M>x_i^{power}</M>
in <A>f</A>.
<P/>
(Not sure if <M>F</M> needs to be a field in fact ...)
<P/>
Related to the GAP command <C>PolynomialCoefficientsPolynomial</C>.

</Description>
</ManSection>

<Example>
gap> F:=GF(11);;
gap> R2:=PolynomialRing(F,2);
PolynomialRing(..., [ x_1, x_2 ])
gap> vars:=IndeterminatesOfPolynomialRing(R2);;
gap> x:=vars[1];; y:=vars[2];;
gap> poly:=y^2-x*(x^2-1);;
gap> PolynomialCoefficientsOfPolynomial(poly,x);
[ x_2^2, Z(11)^0, 0*Z(11), -Z(11)^0 ]
gap> PolynomialCoefficientsOfPolynomial(poly,y);
[ -x_1^3+x_1, 0*Z(11), Z(11)^0 ]
gap> CoefficientMultivariatePolynomial(poly,y,0,R2);
-x_1^3+x_1
gap> CoefficientMultivariatePolynomial(poly,y,1,R2);
0*Z(11)
gap> CoefficientMultivariatePolynomial(poly,y,2,R2);
Z(11)^0
gap> CoefficientMultivariatePolynomial(poly,x,0,R2);
x_2^2
gap> CoefficientMultivariatePolynomial(poly,x,1,R2);
Z(11)^0
gap> CoefficientMultivariatePolynomial(poly,x,2,R2);
0*Z(11)
gap> CoefficientMultivariatePolynomial(poly,x,3,R2);
-Z(11)^0

</Example>
<!--
F:=GF(11);;
R2:=PolynomialRing(F,2);
vars:=IndeterminatesOfPolynomialRing(R2);;
x:=vars[1];; y:=vars[2];;
poly:=y^2-x*(x^2-1);;
PolynomialCoefficientsOfPolynomial(poly,x);
PolynomialCoefficientsOfPolynomial(poly,y);
CoefficientMultivariatePolynomial(poly,y,0,R2);
CoefficientMultivariatePolynomial(poly,y,1,R2);
CoefficientMultivariatePolynomial(poly,y,2,R2);
CoefficientMultivariatePolynomial(poly,x,0,R2);
CoefficientMultivariatePolynomial(poly,x,1,R2);
CoefficientMultivariatePolynomial(poly,x,2,R2);
CoefficientMultivariatePolynomial(poly,x,3,R2);

-->


<ManSection>
<Func Name="SolveLinearSystem" Arg ="L, vars"/>

<Description>
Input:
<A>L</A> is a list of linear forms in the variables <A>vars</A>.
<P/>
Output:
the solution of the system, if its unique.
<P/>
The procedure is straightforward:
Find the associated matrix <M>A</M>,
find the "constant vector" <M>b</M>, and 
solve <M>A*v=b</M>. No error checking is performed.
<P/>
Related to the GAP command <C>SolutionMat( A, b )</C>.

</Description>
</ManSection>

<Example>
gap> F:=GF(11);;
gap> R2:=PolynomialRing(F,2);
PolynomialRing(..., [ x_1, x_2 ])
gap> vars:=IndeterminatesOfPolynomialRing(R2);;
gap> x:=vars[1];; y:=vars[2];;
gap> f:=3*y-3*x+1;; g:=-5*y+2*x-7;;
gap> soln:=SolveLinearSystem([f,g],[x,y]);
[ Z(11)^3, Z(11)^2 ]
gap> Value(f,[x,y],soln); # checking okay
0*Z(11)
gap> Value(g,[x,y],col); # checking okay
0*Z(11)

</Example>
<!--
F:=GF(11);;
R2:=PolynomialRing(F,2);
vars:=IndeterminatesOfPolynomialRing(R2);;
x:=vars[1];; y:=vars[2];;
f:=3*y-3*x+1;; g:=-5*y+2*x-7;;
soln:=SolveLinearSystem([f,g],[x,y]);
Value(f,[x,y],soln); # checking okay
Value(g,[x,y],col); # checking okay
-->




<ManSection>
<Func Name="GuavaVersion" Arg="  "/>

<Description>
Returns the current version of Guava. Same as 
<C>guava\_version()</C>.

</Description>
</ManSection>

<Example>
gap> GuavaVersion();
"3.11"

</Example>
<!--

-->

<ManSection>
<Func Name="ZechLog" Arg=" x b F "/>

<Description>
Returns the Zech log of x to base b, ie the i such that 
$x+1=b^i$, so $y+z=y(1+z/y)=b^k$, where 
k=Log(y,b)+ZechLog(z/y,b) and b must be a primitive element of F.

</Description>
</ManSection>

<Example>
gap> F:=GF(11);; l := One(F);;
gap> ZechLog(2*l,8*l,F);
-24
gap> 8*l+l;(2*l)^(-24);
Z(11)^6
Z(11)^6

</Example>
<!--
F:=GF(11);; l := One(F);;
ZechLog(2*l,8*l,F);
8*l+l;(2*l)^(-24);

-->


<ManSection>
<Func Name="CoefficientToPolynomial" Arg=" coeffs R "/>

<Description>
The function <C>CoefficientToPolynomial</C> returns the 
degree <M>d-1</M> polynomial <M>c_0+c_1x+...+c_{d-1}x^{d-1}</M>, where 
<A>coeffs</A> is a list of elements of a field,
<M>coeffs=\{ c_0,...,c_{d-1}\}</M>, and <A>R</A> is a
univariate polynomial ring.
</Description>
</ManSection>

<Example>
gap> F:=GF(11);
GF(11)
gap> R1:=PolynomialRing(F,["a"]);;
gap> var1:=IndeterminatesOfPolynomialRing(R1);; a:=var1[1];;
gap> coeffs:=Z(11)^0*[1,2,3,4];
[ Z(11)^0, Z(11), Z(11)^8, Z(11)^2 ]
gap> CoefficientToPolynomial(coeffs,R1);
Z(11)^2*a^3+Z(11)^8*a^2+Z(11)*a+Z(11)^0
</Example>
<!--
F:=GF(11);
R1:=PolynomialRing(F,["a"]);;
var1:=IndeterminatesOfPolynomialRing(R1);; a:=var1[1];;
coeffs:=Z(11)^0*[1,2,3,4];
CoefficientToPolynomial(coeffs,R1);
-->

<ManSection>
<Func Name="DegreesMonomialTerm" Arg=" m R "/>

<Description>
The function <C>DegreesMonomialTerm</C> returns the 
list of degrees to which each variable in the 
multivariate polynomial ring 
<A>R</A> occurs in the monomial <A>m</A>, where 
<A>coeffs</A> is a list of elements of a field.
</Description>
</ManSection>

<Example>
gap> F:=GF(11);
GF(11)
gap> R1:=PolynomialRing(F,["a"]);;
gap> var1:=IndeterminatesOfPolynomialRing(R1);; a:=var1[1];;
gap> b:=X(F,"b",var1);
b
gap> var2:=Concatenation(var1,[b]);
[ a, b ]
gap> R2:=PolynomialRing(F,var2);
PolynomialRing(..., [ a, b ])
gap> c:=X(F,"c",var2);
c
gap> var3:=Concatenation(var2,[c]);
[ a, b, c ]
gap> R3:=PolynomialRing(F,var3);
PolynomialRing(..., [ a, b, c ])
gap> m:=b^3*c^7;
b^3*c^7
gap> DegreesMonomialTerm(m,R3);
[ 0, 3, 7 ]
</Example>
<!--
F:=GF(11);
R1:=PolynomialRing(F,["a"]);;
var1:=IndeterminatesOfPolynomialRing(R1);; a:=var1[1];;
b:=X(F,"b",var1);
var2:=Concatenation(var1,[b]);
R2:=PolynomialRing(F,var2);
c:=X(F,"c",var2);
var3:=Concatenation(var2,[c]);
R3:=PolynomialRing(F,var3);
m:=b^3*c^7;
DegreesMonomialTerm(m,R3);
-->

<ManSection>
<Func Name="DivisorsMultivariatePolynomial" Arg=" f R "/>

<Description>
The function <C>DivisorsMultivariatePolynomial</C> returns the 
list of polynomial divisors of <A>f</A> in the 
multivariate polynomial ring <A>R</A> with coefficients in a field.
This program uses a simple but slow algorithm 
(see Joachim von zur Gathen, J&#xfc;rgen Gerhard,
<Cite Key="GG03"/>, exercise 16.10) which first converts the 
multivariate polynomial <A>f</A> to an associated 
univariate polynomial <M>f^*</M>, then 
<C>Factors</C>  <M>f^*</M>, and finally converts these
univariate factors back into the multivariate polynomial
factors of <A>f</A>. Since <C>Factors</C> is non-deterministic,
<C>DivisorsMultivariatePolynomial</C> is non-deterministic
as well.
</Description>
</ManSection>

<Example>
gap> R2:=PolynomialRing(GF(3),["x1","x2"]);
PolynomialRing(..., [ x1, x2 ])
gap> vars:=IndeterminatesOfPolynomialRing(R2);
[ x1, x2 ]
gap> x2:=vars[2];
x2
gap> x1:=vars[1];
x1
gap> f:=x1^3+x2^3;;
gap> DivisorsMultivariatePolynomial(f,R2);
[ x1+x2, x1+x2, x1+x2 ]
</Example>
<!--
R2:=PolynomialRing(GF(3),["x1","x2"]);
vars:=IndeterminatesOfPolynomialRing(R2);
x2:=vars[2];
x1:=vars[1];
f:=x1^3+x2^3;;
DivisorsMultivariatePolynomial(f,R2);
-->


</Section>
</Chapter>

<Chapter>
<Heading>Coding theory functions in GAP</Heading>
<Label Name="Coding theory functions in the GAP"/>

This chapter will recall from the GAP4.4.5 manual some of the
GAP coding theory and finite field functions useful for
coding theory. Some of these functions are 
partially written in C for speed. The main functions are

<List>
<Item>  
<C>AClosestVectorCombinationsMatFFEVecFFE</C>,
</Item>

<Item>  
<C>AClosestVectorCombinationsMatFFEVecFFECoords</C>,
</Item>

<Item>  
<C>CosetLeadersMatFFE</C>, 
</Item>

<Item>  
<C>DistancesDistributionMatFFEVecFFE</C>,
</Item>

<Item>  
<C>DistancesDistributionVecFFEsVecFFE</C>,
</Item>

<Item>  
<C>DistanceVecFFE</C> and <C>WeightVecFFE</C>,
</Item>

<Item>  
<C>ConwayPolynomial</C> and <C>IsCheapConwayPolynomial</C>,
</Item>

<Item>  
<C>IsPrimitivePolynomial</C>,
and <C>RandomPrimitivePolynomial</C>.
</Item>
</List>
However, the GAP command
<C>PrimitivePolynomial</C> returns an integer primitive polynomial
not the finite field kind.
<P/>

<Section>
<Heading>
Distance functions
</Heading>
<Label Name="Distance functions"/>

<ManSection>
<Func Name="AClosestVectorCombinationsMatFFEVecFFE" 
Arg=" mat, F, vec, r, st "/>


<Description>
This command runs through the <A>F</A>-linear 
combinations of the vectors in the rows of 
the matrix <A>mat</A> that can be written as linear combinations of exactly 
<A>r</A> rows (that is without using zero as a coefficient) and returns a 
vector from these that is closest to the vector <A>vec</A>. The length of 
the rows of <A>mat</A> and the length of <A>vec</A> must be equal, 
and all elements must lie in <A>F</A>. 
The rows of <A>mat</A> must be linearly independent. 
If it finds a vector of distance at most <A>st</A>, which must be a 
nonnegative integer, then it stops immediately and returns this vector.

</Description>
</ManSection>

<Example>
gap> F:=GF(3);;
gap> x:= Indeterminate( F );; pol:= x^2+1;
x_1^2+Z(3)^0
gap> C := GeneratorPolCode(pol,8,F);
a cyclic [8,6,1..2]1..2 code defined by generator polynomial over GF(3)
gap> v:=Codeword("12101111");
[ 1 2 1 0 1 1 1 1 ]
gap> v:=VectorCodeword(v);
[ Z(3)^0, Z(3), Z(3)^0, 0*Z(3), Z(3)^0, Z(3)^0, Z(3)^0, Z(3)^0 ]
gap> G:=GeneratorMat(C);
[ [ Z(3)^0, 0*Z(3), Z(3)^0, 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3) ],
  [ 0*Z(3), Z(3)^0, 0*Z(3), Z(3)^0, 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3) ],
  [ 0*Z(3), 0*Z(3), Z(3)^0, 0*Z(3), Z(3)^0, 0*Z(3), 0*Z(3), 0*Z(3) ],
  [ 0*Z(3), 0*Z(3), 0*Z(3), Z(3)^0, 0*Z(3), Z(3)^0, 0*Z(3), 0*Z(3) ],
  [ 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3), Z(3)^0, 0*Z(3), Z(3)^0, 0*Z(3) ],
  [ 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3), Z(3)^0, 0*Z(3), Z(3)^0 ] ]
gap> AClosestVectorCombinationsMatFFEVecFFE(G,F,v,1,1);
[ 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3), Z(3)^0, 0*Z(3), Z(3)^0 ]
</Example>
<!--
F:=GF(3);; x:= Indeterminate( F );; pol:= x^2+1;
C := GeneratorPolCode(pol,8,F);
v:=Codeword("12101111");
v:=VectorCodeword(v);
G:=GeneratorMat(C);
AClosestVectorCombinationsMatFFEVecFFE(G,F,v,1,1);
-->


<ManSection>
<Func Name="AClosestVectorComb..MatFFEVecFFECoords" 
Arg=" mat, F, vec, r, st "/>

<Description>
<C>AClosestVectorCombinationsMatFFEVecFFECoords</C> 
returns a two element list containing (a) the same closest 
vector as in <C>AClosestVectorCombinationsMatFFEVecFFE</C>,
and (b) a vector <A>v</A> with exactly <A>r</A> non-zero 
entries, such that <M>v*mat</M> is the closest vector.
</Description>
</ManSection>

<Example>
gap> F:=GF(3);;
gap> x:= Indeterminate( F );; pol:= x^2+1;
x_1^2+Z(3)^0
gap> C := GeneratorPolCode(pol,8,F);
a cyclic [8,6,1..2]1..2 code defined by generator polynomial over GF(3)
gap> v:=Codeword("12101111"); v:=VectorCodeword(v);;
[ 1 2 1 0 1 1 1 1 ]
gap> G:=GeneratorMat(C);;
gap> AClosestVectorCombinationsMatFFEVecFFECoords(G,F,v,1,1);
[ [ 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3), Z(3)^0, 0*Z(3), Z(3)^0 ],
  [ 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3), Z(3)^0 ] ]
</Example>
<!--
F:=GF(3);; x:= Indeterminate( F );; pol:= x^2+1;
C := GeneratorPolCode(pol,8,F);
v:=Codeword("12101111"); v:=VectorCodeword(v);;
G:=GeneratorMat(C);;
AClosestVectorCombinationsMatFFEVecFFECoords(G,F,v,1,1);
-->

<ManSection>
<Func Name="DistancesDistributionMatFFEVecFFE" 
Arg=" mat, f, vec "/>

<Description>
<C>DistancesDistributionMatFFEVecFFE</C> 
returns the distances distribution of the vector <A>vec</A> to the vectors 
in the vector space generated by the rows of the matrix <A>mat</A> over the finite field <A>f</A>. 
All vectors must have the same length, and all elements must lie in a common 
field. The distances distribution is a list <M>d</M> of length 
<M>Length(vec)+1</M>, such that the value <M>d[i]</M> is the number of 
vectors in vecs that have distance <M>i+1</M> to <A>vec</A>.
</Description>
</ManSection>

<Example>
gap> v:=[ Z(3)^0, Z(3), Z(3)^0, 0*Z(3), Z(3)^0, Z(3)^0, Z(3)^0, Z(3)^0 ];;
gap> vecs:=[ [ Z(3)^0, 0*Z(3), Z(3)^0, 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3) ],
>   [ 0*Z(3), Z(3)^0, 0*Z(3), Z(3)^0, 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3) ],
>   [ 0*Z(3), 0*Z(3), Z(3)^0, 0*Z(3), Z(3)^0, 0*Z(3), 0*Z(3), 0*Z(3) ],
>   [ 0*Z(3), 0*Z(3), 0*Z(3), Z(3)^0, 0*Z(3), Z(3)^0, 0*Z(3), 0*Z(3) ],
>   [ 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3), Z(3)^0, 0*Z(3), Z(3)^0, 0*Z(3) ],
>   [ 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3), Z(3)^0, 0*Z(3), Z(3)^0 ] ];;
gap> DistancesDistributionMatFFEVecFFE(vecs,GF(3),v);
[ 0, 4, 6, 60, 109, 216, 192, 112, 30 ]
</Example>
<!--
v:=[ Z(3)^0, Z(3), Z(3)^0, 0*Z(3), Z(3)^0, Z(3)^0, Z(3)^0, Z(3)^0 ];;
vecs:=[ [ Z(3)^0, 0*Z(3), Z(3)^0, 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3) ],
   [ 0*Z(3), Z(3)^0, 0*Z(3), Z(3)^0, 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3) ],
   [ 0*Z(3), 0*Z(3), Z(3)^0, 0*Z(3), Z(3)^0, 0*Z(3), 0*Z(3), 0*Z(3) ],
   [ 0*Z(3), 0*Z(3), 0*Z(3), Z(3)^0, 0*Z(3), Z(3)^0, 0*Z(3), 0*Z(3) ],
   [ 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3), Z(3)^0, 0*Z(3), Z(3)^0, 0*Z(3) ],
   [ 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3), Z(3)^0, 0*Z(3), Z(3)^0 ] ];;
DistancesDistributionMatFFEVecFFE(vecs,GF(3),v);
-->

<ManSection>
<Func Name="DistancesDistributionVecFFEsVecFFE" 
Arg=" vecs, vec "/>

<Description>
<C>DistancesDistributionVecFFEsVecFFE</C> returns 
the distances distribution of the vector 
<A>vec</A> to the vectors in the list <A>vecs</A>. All vectors must 
have the same length, and all elements must lie in a 
common field. The distances distribution is a list <M>d</M> of 
length <M>Length(vec)+1</M>, such that the value <M>d[i]</M> 
is the number of vectors in <A>vecs</A> that have distance 
<M>i+1</M> to <A>vec</A>.

</Description>
</ManSection>

<Example>
gap> v:=[ Z(3)^0, Z(3), Z(3)^0, 0*Z(3), Z(3)^0, Z(3)^0, Z(3)^0, Z(3)^0 ];;
gap> vecs:=[ [ Z(3)^0, 0*Z(3), Z(3)^0, 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3) ],
>   [ 0*Z(3), Z(3)^0, 0*Z(3), Z(3)^0, 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3) ],
>   [ 0*Z(3), 0*Z(3), Z(3)^0, 0*Z(3), Z(3)^0, 0*Z(3), 0*Z(3), 0*Z(3) ],
>   [ 0*Z(3), 0*Z(3), 0*Z(3), Z(3)^0, 0*Z(3), Z(3)^0, 0*Z(3), 0*Z(3) ],
>   [ 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3), Z(3)^0, 0*Z(3), Z(3)^0, 0*Z(3) ],
>   [ 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3), Z(3)^0, 0*Z(3), Z(3)^0 ] ];;
gap> DistancesDistributionVecFFEsVecFFE(vecs,v);
[ 0, 0, 0, 0, 0, 4, 0, 1, 1 ]
</Example>
<!--
v:=[ Z(3)^0, Z(3), Z(3)^0, 0*Z(3), Z(3)^0, Z(3)^0, Z(3)^0, Z(3)^0 ];;
vecs:=[ [ Z(3)^0, 0*Z(3), Z(3)^0, 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3) ],
   [ 0*Z(3), Z(3)^0, 0*Z(3), Z(3)^0, 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3) ],
   [ 0*Z(3), 0*Z(3), Z(3)^0, 0*Z(3), Z(3)^0, 0*Z(3), 0*Z(3), 0*Z(3) ],
   [ 0*Z(3), 0*Z(3), 0*Z(3), Z(3)^0, 0*Z(3), Z(3)^0, 0*Z(3), 0*Z(3) ],
   [ 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3), Z(3)^0, 0*Z(3), Z(3)^0, 0*Z(3) ],
   [ 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3), 0*Z(3), Z(3)^0, 0*Z(3), Z(3)^0 ] ];;
DistancesDistributionVecFFEsVecFFE(vecs,v);
-->

<ManSection>
<Func Name="WeightVecFFE" Arg=" vec "/>


<Description>
<C>WeightVecFFE</C> returns the weight of the finite field 
vector <A>vec</A>, i.e. the number of nonzero entries.
</Description>
</ManSection>

<Example>
gap> v:=[ Z(3)^0, Z(3), Z(3)^0, 0*Z(3), Z(3)^0, Z(3)^0, Z(3)^0, Z(3)^0 ];;
gap> WeightVecFFE(v);
7
</Example>
<!--
v:=[ Z(3)^0, Z(3), Z(3)^0, 0*Z(3), Z(3)^0, Z(3)^0, Z(3)^0, Z(3)^0 ];;
WeightVecFFE(v);
-->

<Index>
Hamming metric
</Index>

<ManSection>
<Func Name="DistanceVecFFE" Arg=" vec1 vec2 "/>


<Description>
The <E>Hamming metric</E> on <M>GF(q)^n</M> is the function
<Display>
dist((v_1,...,v_n),(w_1,...,w_n))
=|\{i\in [1..n]\ |\ v_i\not= w_i\}|.
</Display>
This is also called the (Hamming) distance
between <M>v=(v_1,...,v_n)</M> and <M>w=(w_1,...,w_n)</M>.
<C>DistanceVecFFE</C> 
returns the distance between the two vectors <A>vec1</A> and 
<A>vec2</A>, which must have the same length and whose 
elements must lie in a common field. The distance is the number 
of places where <A>vec1</A> and <A>vec2</A> differ.
</Description>
</ManSection>

<Example>
gap> v1:=[ Z(3)^0, Z(3), Z(3)^0, 0*Z(3), Z(3)^0, Z(3)^0, Z(3)^0, Z(3)^0 ];;
gap> v2:=[ Z(3), Z(3)^0, Z(3)^0, 0*Z(3), Z(3)^0, Z(3)^0, Z(3)^0, Z(3)^0 ];;
gap> DistanceVecFFE(v1,v2);
2
</Example>
<!--
v1:=[ Z(3)^0, Z(3), Z(3)^0, 0*Z(3), Z(3)^0, Z(3)^0, Z(3)^0, Z(3)^0 ];;
v2:=[ Z(3), Z(3)^0, Z(3)^0, 0*Z(3), Z(3)^0, Z(3)^0, Z(3)^0, Z(3)^0 ];;
DistanceVecFFE(v1,v2);
-->

</Section>

<Section>
<Heading>
Other functions
</Heading>
<Label Name="Other functions"/>

We basically repeat, with minor variation, the material
in the GAP manual or from Frank Luebeck's website
<URL>http://www.math.rwth-aachen.de/~Frank.Luebeck/data/ConwayPol</URL> 
on Conway polynomials.

<Index><M>GF(p)</M></Index>

The <B>prime fields</B>: If <M>p\geq 2</M> is a prime then
<M>GF(p)</M> denotes the field <M>{\mathbb{Z}}/p{\mathbb{Z}}</M>,
with addition and multiplication performed mod <M>p</M>.
<P/>
<Index><M>GF(q)</M></Index>
The <B>prime power fields</B>: Suppose <M>q=p^r</M> is a prime
power, <M>r>1</M>, and put <M>F=GF(p)</M>. Let <M>F[x]</M> 
denote the ring of all polynomials over <M>F</M>
and let <M>f(x)</M> denote a monic irreducible
polynomial in <M>F[x]</M> of degree <M>r</M>. The quotient
<M>E = F[x]/(f(x))= F[x]/f(x)F[x]</M> is a field
with <M>q</M> elements. 
If <M>f(x)</M> and <M>E</M> are related in this way, we say that
<M>f(x)</M> is the <B>defining polynomial</B> of <M>E</M>.
<Index>defining polynomial</Index> 
Any defining polynomial factors completely into 
distinct linear factors over the field it defines.
<P/>
For any finite field <M>F</M>, the multiplicative group of
non-zero elements <M>F^\times</M> is a cyclic group. An 
<M>\alpha \in F</M> is called a <B>primitive element</B> if it is a 
generator of <M>F^\times</M>. A defining polynomial
<M>f(x)</M> of <M>F</M> is said to be <B>primitive</B> if
it has a root in <M>F</M> which is a primitive element.
<Index>primitive element</Index> 


<ManSection>
<Func Name="ConwayPolynomial" Arg=" p n "/>


<Description>
A standard notation for the elements of <M>GF(p)</M> is 
given via the representatives <M>0, ..., p-1</M> of the cosets modulo <M>p</M>. 
We order these elements by <M>0 \ \ \langle\ \  1 \ \ \langle\ \  2 \ \ \langle\ \  ... \ \ \langle\ \  p-1</M>.
We introduce an ordering of the polynomials of degree <M>r</M> over <M>GF(p)</M>. 
Let <M>g(x) = g_rx^r + ... + g_0</M> and 
<M>h(x) = h_rx^r + ... + h_0</M> (by convention, <M>g_i=h_i=0</M> for <M>i\ \ \rangle\ \  r</M>). 
Then we define <M>g \ \ \langle\ \  h</M> if and only if 
there is an index <M>k</M> with <M>g_i = h_i</M> for <M>i \ \ \rangle\ \  k</M> and 
<M>(-1)^{r-k} g_k \ \ \langle\ \  (-1)^{r-k} h_k</M>.
<P/>
The <B>Conway polynomial</B> <M>f_{p,r}(x)</M> for <M>GF(p^r)</M> is the smallest 
polynomial of degree <M>r</M> with respect to this ordering such that:

<List>
<Item>
 <M>f_{p,r}(x)</M> is monic,
</Item>
<Item>
 <M>f_{p,r}(x)</M> is primitive, that is, any zero is a generator of 
the (cyclic) multiplicative group of <M>GF(p^r)</M>,
</Item>
<Item>
for each proper divisor <M>m</M> of <M>r</M> we have that 
<M>f_{p,m}(x^{(p^r-1) / (p^m-1)}) \equiv 0 \pmod{f_{p,r}(x)}</M>; 
that is, the <M>(p^r-1) / (p^m-1)</M>-th power of a zero of 
<M>f_{p,r}(x)</M> is a zero of <M>f_{p,m}(x)</M>.
</Item>
</List>
<P/>
<C>ConwayPolynomial(p,n)</C> returns the polynomial <M>f_{p,r}(x)</M> defined above.
<P/>
<C>IsCheapConwayPolynomial(p,n)</C> 
returns true if <C>ConwayPolynomial( p, n )</C> will give a result in 
reasonable time. This is either the case when this polynomial is 
pre-computed, or if <M>n,p</M> are not too big. 
</Description>
</ManSection>
<Index>IsCheapConwayPolynomial</Index>

<ManSection>
<Func Name="RandomPrimitivePolynomial" Arg=" F n "/>


<Description>
For a finite field <A>F</A> and a positive integer <A>n</A> this function 
returns a primitive polynomial of degree <A>n</A> over <A>F</A>, 
that is a zero of this polynomial has maximal multiplicative order 
<M>|F|^n-1</M>.
<P/>
<C>IsPrimitivePolynomial(f)</C> can be used to check if a
univariate polynomial <A>f</A> is primitive or not.  
</Description>
</ManSection>
<Index>IsPrimitivePolynomial</Index>


</Section>
</Chapter>

<Chapter>
<Heading>
GNU Free Documentation License
</Heading>

	GNU Free Documentation License
		  Version 1.2, November 2002

<P/>
 Copyright (C) 2000,2001,2002  Free Software Foundation, Inc.
     51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

<P/>
0. PREAMBLE
<P/>
The purpose of this License is to make a manual, textbook, or other
functional and useful document "free" in the sense of freedom: to
assure everyone the effective freedom to copy and redistribute it,
with or without modifying it, either commercially or noncommercially.
Secondarily, this License preserves for the author and publisher a way
to get credit for their work, while not being considered responsible
for modifications made by others.
<P/>
This License is a kind of "copyleft", which means that derivative
works of the document must themselves be free in the same sense.  It
complements the GNU General Public License, which is a copyleft
license designed for free software.
<P/>
We have designed this License in order to use it for manuals for free
software, because free software needs free documentation: a free
program should come with manuals providing the same freedoms that the
software does.  But this License is not limited to software manuals;
it can be used for any textual work, regardless of subject matter or
whether it is published as a printed book.  We recommend this License
principally for works whose purpose is instruction or reference.
<P/>

1. APPLICABILITY AND DEFINITIONS
<P/>
This License applies to any manual or other work, in any medium, that
contains a notice placed by the copyright holder saying it can be
distributed under the terms of this License.  Such a notice grants a
world-wide, royalty-free license, unlimited in duration, to use that
work under the conditions stated herein.  The "Document", below,
refers to any such manual or work.  Any member of the public is a
licensee, and is addressed as "you".  You accept the license if you
copy, modify or distribute the work in a way requiring permission
under copyright law.
<P/>
A "Modified Version" of the Document means any work containing the
Document or a portion of it, either copied verbatim, or with
modifications and/or translated into another language.
<P/>
A "Secondary Section" is a named appendix or a front-matter section of
the Document that deals exclusively with the relationship of the
publishers or authors of the Document to the Document's overall subject
(or to related matters) and contains nothing that could fall directly
within that overall subject.  (Thus, if the Document is in part a
textbook of mathematics, a Secondary Section may not explain any
mathematics.)  The relationship could be a matter of historical
connection with the subject or with related matters, or of legal,
commercial, philosophical, ethical or political position regarding
them.
<P/>
The "Invariant Sections" are certain Secondary Sections whose titles
are designated, as being those of Invariant Sections, in the notice
that says that the Document is released under this License.  If a
section does not fit the above definition of Secondary then it is not
allowed to be designated as Invariant.  The Document may contain zero
Invariant Sections.  If the Document does not identify any Invariant
Sections then there are none.
<P/>
The "Cover Texts" are certain short passages of text that are listed,
as Front-Cover Texts or Back-Cover Texts, in the notice that says that
the Document is released under this License.  A Front-Cover Text may
be at most 5 words, and a Back-Cover Text may be at most 25 words.
<P/>
A "Transparent" copy of the Document means a machine-readable copy,
represented in a format whose specification is available to the
general public, that is suitable for revising the document
straightforwardly with generic text editors or (for images composed of
pixels) generic paint programs or (for drawings) some widely available
drawing editor, and that is suitable for input to text formatters or
for automatic translation to a variety of formats suitable for input
to text formatters.  A copy made in an otherwise Transparent file
format whose markup, or absence of markup, has been arranged to thwart
or discourage subsequent modification by readers is not Transparent.
An image format is not Transparent if used for any substantial amount
of text.  A copy that is not "Transparent" is called "Opaque".
<P/>
Examples of suitable formats for Transparent copies include plain
ASCII without markup, Texinfo input format, LaTeX input format, SGML
or XML using a publicly available DTD, and standard-conforming simple
HTML, PostScript or PDF designed for human modification.  Examples of
transparent image formats include PNG, XCF and JPG.  Opaque formats
include proprietary formats that can be read and edited only by
proprietary word processors, SGML or XML for which the DTD and/or
processing tools are not generally available, and the
machine-generated HTML, PostScript or PDF produced by some word
processors for output purposes only.
<P/>
The "Title Page" means, for a printed book, the title page itself,
plus such following pages as are needed to hold, legibly, the material
this License requires to appear in the title page.  For works in
formats which do not have any title page as such, "Title Page" means
the text near the most prominent appearance of the work's title,
preceding the beginning of the body of the text.
<P/>
A section "Entitled XYZ" means a named subunit of the Document whose
title either is precisely XYZ or contains XYZ in parentheses following
text that translates XYZ in another language.  (Here XYZ stands for a
specific section name mentioned below, such as "Acknowledgements",
"Dedications", "Endorsements", or "History".)  To "Preserve the Title"
of such a section when you modify the Document means that it remains a
section "Entitled XYZ" according to this definition.
<P/>
The Document may include Warranty Disclaimers next to the notice which
states that this License applies to the Document.  These Warranty
Disclaimers are considered to be included by reference in this
License, but only as regards disclaiming warranties: any other
implication that these Warranty Disclaimers may have is void and has
no effect on the meaning of this License.
<P/>

2. VERBATIM COPYING
<P/>
You may copy and distribute the Document in any medium, either
commercially or noncommercially, provided that this License, the
copyright notices, and the license notice saying this License applies
to the Document are reproduced in all copies, and that you add no other
conditions whatsoever to those of this License.  You may not use
technical measures to obstruct or control the reading or further
copying of the copies you make or distribute.  However, you may accept
compensation in exchange for copies.  If you distribute a large enough
number of copies you must also follow the conditions in section 3.
<P/>
You may also lend copies, under the same conditions stated above, and
you may publicly display copies.
<P/>

3. COPYING IN QUANTITY
<P/>
If you publish printed copies (or copies in media that commonly have
printed covers) of the Document, numbering more than 100, and the
Document's license notice requires Cover Texts, you must enclose the
copies in covers that carry, clearly and legibly, all these Cover
Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on
the back cover.  Both covers must also clearly and legibly identify
you as the publisher of these copies.  The front cover must present
the full title with all words of the title equally prominent and
visible.  You may add other material on the covers in addition.
Copying with changes limited to the covers, as long as they preserve
the title of the Document and satisfy these conditions, can be treated
as verbatim copying in other respects.
<P/>
If the required texts for either cover are too voluminous to fit
legibly, you should put the first ones listed (as many as fit
reasonably) on the actual cover, and continue the rest onto adjacent
pages.
<P/>
If you publish or distribute Opaque copies of the Document numbering
more than 100, you must either include a machine-readable Transparent
copy along with each Opaque copy, or state in or with each Opaque copy
a computer-network location from which the general network-using
public has access to download using public-standard network protocols
a complete Transparent copy of the Document, free of added material.
If you use the latter option, you must take reasonably prudent steps,
when you begin distribution of Opaque copies in quantity, to ensure
that this Transparent copy will remain thus accessible at the stated
location until at least one year after the last time you distribute an
Opaque copy (directly or through your agents or retailers) of that
edition to the public.
<P/>
It is requested, but not required, that you contact the authors of the
Document well before redistributing any large number of copies, to give
them a chance to provide you with an updated version of the Document.
<P/>

4. MODIFICATIONS
<P/>
You may copy and distribute a Modified Version of the Document under
the conditions of sections 2 and 3 above, provided that you release
the Modified Version under precisely this License, with the Modified
Version filling the role of the Document, thus licensing distribution
and modification of the Modified Version to whoever possesses a copy
of it.  In addition, you must do these things in the Modified Version:
<P/>
A. Use in the Title Page (and on the covers, if any) a title distinct
   from that of the Document, and from those of previous versions
   (which should, if there were any, be listed in the History section
   of the Document).  You may use the same title as a previous version
   if the original publisher of that version gives permission.
<P/>
B. List on the Title Page, as authors, one or more persons or entities
   responsible for authorship of the modifications in the Modified
   Version, together with at least five of the principal authors of the
   Document (all of its principal authors, if it has fewer than five),
   unless they release you from this requirement.
<P/>
C. State on the Title page the name of the publisher of the
   Modified Version, as the publisher.
<P/>
D. Preserve all the copyright notices of the Document.
<P/>
E. Add an appropriate copyright notice for your modifications
   adjacent to the other copyright notices.
<P/>
F. Include, immediately after the copyright notices, a license notice
   giving the public permission to use the Modified Version under the
   terms of this License, in the form shown in the Addendum below.
<P/>
G. Preserve in that license notice the full lists of Invariant Sections
   and required Cover Texts given in the Document's license notice.
<P/>
H. Include an unaltered copy of this License.
<P/>
I. Preserve the section Entitled "History", Preserve its Title, and add
   to it an item stating at least the title, year, new authors, and
   publisher of the Modified Version as given on the Title Page.  If
   there is no section Entitled "History" in the Document, create one
   stating the title, year, authors, and publisher of the Document as
   given on its Title Page, then add an item describing the Modified
   Version as stated in the previous sentence.
<P/>
J. Preserve the network location, if any, given in the Document for
   public access to a Transparent copy of the Document, and likewise
   the network locations given in the Document for previous versions
   it was based on.  These may be placed in the "History" section.
   You may omit a network location for a work that was published at
   least four years before the Document itself, or if the original
   publisher of the version it refers to gives permission.
<P/>
K. For any section Entitled "Acknowledgements" or "Dedications",
   Preserve the Title of the section, and preserve in the section all
   the substance and tone of each of the contributor acknowledgements
   and/or dedications given therein.
<P/>
L. Preserve all the Invariant Sections of the Document,
   unaltered in their text and in their titles.  Section numbers
   or the equivalent are not considered part of the section titles.
<P/>
M. Delete any section Entitled "Endorsements".  Such a section
   may not be included in the Modified Version.
<P/>
N. Do not retitle any existing section to be Entitled "Endorsements"
   or to conflict in title with any Invariant Section.
<P/>
O. Preserve any Warranty Disclaimers.

<P/>
If the Modified Version includes new front-matter sections or
appendices that qualify as Secondary Sections and contain no material
copied from the Document, you may at your option designate some or all
of these sections as invariant.  To do this, add their titles to the
list of Invariant Sections in the Modified Version's license notice.
These titles must be distinct from any other section titles.
<P/>
You may add a section Entitled "Endorsements", provided it contains
nothing but endorsements of your Modified Version by various
parties--for example, statements of peer review or that the text has
been approved by an organization as the authoritative definition of a
standard.
<P/>
You may add a passage of up to five words as a Front-Cover Text, and a
passage of up to 25 words as a Back-Cover Text, to the end of the list
of Cover Texts in the Modified Version.  Only one passage of
Front-Cover Text and one of Back-Cover Text may be added by (or
through arrangements made by) any one entity.  If the Document already
includes a cover text for the same cover, previously added by you or
by arrangement made by the same entity you are acting on behalf of,
you may not add another; but you may replace the old one, on explicit
permission from the previous publisher that added the old one.
<P/>
The author(s) and publisher(s) of the Document do not by this License
give permission to use their names for publicity for or to assert or
imply endorsement of any Modified Version.

<P/>
5. COMBINING DOCUMENTS
<P/>
You may combine the Document with other documents released under this
License, under the terms defined in section 4 above for modified
versions, provided that you include in the combination all of the
Invariant Sections of all of the original documents, unmodified, and
list them all as Invariant Sections of your combined work in its
license notice, and that you preserve all their Warranty Disclaimers.
<P/>
The combined work need only contain one copy of this License, and
multiple identical Invariant Sections may be replaced with a single
copy.  If there are multiple Invariant Sections with the same name but
different contents, make the title of each such section unique by
adding at the end of it, in parentheses, the name of the original
author or publisher of that section if known, or else a unique number.
Make the same adjustment to the section titles in the list of
Invariant Sections in the license notice of the combined work.
<P/>
In the combination, you must combine any sections Entitled "History"
in the various original documents, forming one section Entitled
"History"; likewise combine any sections Entitled "Acknowledgements",
and any sections Entitled "Dedications".  You must delete all sections
Entitled "Endorsements".
<P/>

6. COLLECTIONS OF DOCUMENTS
<P/>
You may make a collection consisting of the Document and other documents
released under this License, and replace the individual copies of this
License in the various documents with a single copy that is included in
the collection, provided that you follow the rules of this License for
verbatim copying of each of the documents in all other respects.
<P/>
You may extract a single document from such a collection, and distribute
it individually under this License, provided you insert a copy of this
License into the extracted document, and follow this License in all
other respects regarding verbatim copying of that document.

<P/>
7. AGGREGATION WITH INDEPENDENT WORKS
<P/>
A compilation of the Document or its derivatives with other separate
and independent documents or works, in or on a volume of a storage or
distribution medium, is called an "aggregate" if the copyright
resulting from the compilation is not used to limit the legal rights
of the compilation's users beyond what the individual works permit.
When the Document is included in an aggregate, this License does not
apply to the other works in the aggregate which are not themselves
derivative works of the Document.
<P/>
If the Cover Text requirement of section 3 is applicable to these
copies of the Document, then if the Document is less than one half of
the entire aggregate, the Document's Cover Texts may be placed on
covers that bracket the Document within the aggregate, or the
electronic equivalent of covers if the Document is in electronic form.
Otherwise they must appear on printed covers that bracket the whole
aggregate.

<P/>
8. TRANSLATION
<P/>
Translation is considered a kind of modification, so you may
distribute translations of the Document under the terms of section 4.
Replacing Invariant Sections with translations requires special
permission from their copyright holders, but you may include
translations of some or all Invariant Sections in addition to the
original versions of these Invariant Sections.  You may include a
translation of this License, and all the license notices in the
Document, and any Warranty Disclaimers, provided that you also include
the original English version of this License and the original versions
of those notices and disclaimers.  In case of a disagreement between
the translation and the original version of this License or a notice
or disclaimer, the original version will prevail.
<P/>
If a section in the Document is Entitled "Acknowledgements",
"Dedications", or "History", the requirement (section 4) to Preserve
its Title (section 1) will typically require changing the actual
title.
<P/>

9. TERMINATION
<P/>
You may not copy, modify, sublicense, or distribute the Document except
as expressly provided for under this License.  Any other attempt to
copy, modify, sublicense or distribute the Document is void, and will
automatically terminate your rights under this License.  However,
parties who have received copies, or rights, from you under this
License will not have their licenses terminated so long as such
parties remain in full compliance.
<P/>

10. FUTURE REVISIONS OF THIS LICENSE
<P/>
The Free Software Foundation may publish new, revised versions
of the GNU Free Documentation 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.  See
https://www.gnu.org/copyleft/.
<P/>
Each version of the License is given a distinguishing version number.
If the Document specifies that a particular numbered version of this
License "or any later version" applies to it, you have the option of
following the terms and conditions either of that specified version or
of any later version that has been published (not as a draft) by the
Free Software Foundation.  If the Document does not specify a version
number of this License, you may choose any version ever published (not
as a draft) by the Free Software Foundation.


</Chapter>

</Body>
<Bibliography Databases="guava_bib.xml"/>
<TheIndex/>                                               
</Book>



