From 709828d59e3defe4f81f6d6e89383fc15b4c6b4e Mon Sep 17 00:00:00 2001
From: LeonidPryadko <63686094+LeonidPryadko@users.noreply.github.com>
Date: Fri, 12 Jan 2024 16:50:54 -0800
Subject: [PATCH] MTXE file parsing modified (#34)
* File parsing modified
* additional checks before calling
---
examples/examples.g | 18 ++
lib/qdistrnd.g | 488 ++++++++++++++++++++++++--------------------
tst/qdistrnd02.tst | 20 +-
3 files changed, 306 insertions(+), 220 deletions(-)
diff --git a/examples/examples.g b/examples/examples.g
index 67a8fff..8171e11 100644
--- a/examples/examples.g
+++ b/examples/examples.g
@@ -162,6 +162,7 @@ DistRandStab(H,100,0,2 : field:=F);
#! 2
#! @EndExample
+#! @Chapter AllFunctions
#! @Section HelperFunctions
#! @Subsection Examples
#! @BeginExample
@@ -182,3 +183,20 @@ Display(mat);
#! . . . . . . . . 1 2
#! @EndExample
+#! These examples illustrate the allowed format of field definitions in the header of an `MTXE` file:
+#! @BeginExample
+QDR_ParseFieldStr("Z(5)");
+#! Z(5)
+QDR_ParseFieldStr("Z(17)");
+#! Z(17)
+QDR_ParseFieldStr("GF(5^2)");
+#! GF(5^2)
+QDR_ParseFieldStr("GF(25)");
+#! GF(5^2)
+QDR_ParseFieldStr("GF(125^2)");
+#! GF(5^6)
+#! @EndExample
+#! @BeginExample
+QDR_ParsePolyStr(GF(25),"x^2+1");
+#! x^2+Z(5)^0
+#! @EndExample
diff --git a/lib/qdistrnd.g b/lib/qdistrnd.g
index 411ba69..f8c71d1 100644
--- a/lib/qdistrnd.g
+++ b/lib/qdistrnd.g
@@ -15,8 +15,8 @@
#! @Description Calculate the average of the components of a numerical `vector`
#! @Arguments vector
-DeclareGlobalFunction("QDR_AverageCalc");
-InstallGlobalFunction("QDR_AverageCalc",
+#DeclareGlobalFunction("QDR_AverageCalc");
+BindGlobal("QDR_AverageCalc",
function(mult)
return 1.0*Sum(mult)/Length(mult);
end
@@ -34,8 +34,8 @@ InstallGlobalFunction("QDR_AverageCalc",
#! **Note: the parity of vector `length` and the format are not verified!!!**
#! @Returns symplectic weight of a vector
#! @Arguments vector, field
-DeclareGlobalFunction("QDR_SymplVecWeight");
-InstallGlobalFunction("QDR_SymplVecWeight",
+#DeclareGlobalFunction("QDR_SymplVecWeight");
+BindGlobal("QDR_SymplVecWeight",
function(vec, F)
local wgt, i, len;
# local variables: wgt - the weight, i - for "for" loop, len - length of vec
@@ -100,18 +100,94 @@ InstallGlobalFunction("QDR_DoProbOut",
end
);
+#! @Description Parse a string describing a Galois field
+#! Supported formats: `Z(p)`, `GF(q)`, and `GF(q^m)`,
+#! where `p` must be a prime, `q` a prime or a power of a prime, and `m` a natural integer.
+#! No spaces are allowed.
+#! @Returns the corresponding Galois field
+#! @Arguments str
+#DeclareGlobalFunction("QDR_ParseFieldStr");
+BindGlobal("QDR_ParseFieldStr",
+ function(str)
+ local body, q;
+ if EndsWith(str,")") then
+ if StartsWith(str,"Z(") then
+ body := str{[3..Length(str)-1]};
+ q := Int(body);
+ if IsInt(q) and IsPrimeInt(q) then
+ return Z(q);
+ else
+ Print("\n Argument of ",str,"should be prime\n");
+ fi;
+ elif StartsWith(str,"GF(") then
+ body := str{[4..Length(str)-1]};
+ q := Int(body);
+ if IsInt(q) then
+ if IsPrimePowerInt(q) then
+ return GF(q);
+ fi;
+ else
+ q := SplitString(body,"^");
+ if Length(q) = 2 then
+ if IsInt(Int(q[1])) and
+ IsInt(Int(q[2])) and
+ IsPrimePowerInt(Int(q[1])^Int(q[2]))
+ then
+ return GF(Int(q[1])^Int(q[2]));
+ fi;
+ fi;
+ fi;
+ Print("\n Argument of ",str,"should be a prime power\n");
+ fi;
+ fi;
+ Error("\n QDR_ParseFieldStr: Invalid argument format str=",str,
+ "\n valid format: 'GF(p)', 'Z(p)', 'GF(p^m)', 'GF(q)'",
+ "\n with 'p' prime, 'm' positive integer, and 'q' a prime power\n");
+ end
+ );
+
+#! @Description Parse string `str` as a polynomial over the field `F`.
+#! Only characters in "0123456789*+-^x" are allowed in the string.
+#! In particular, no spaces are allowed.
+#! @Returns the corresponding polynomial
+#! @Arguments F, str
+#DeclareGlobalFunction("QDR_ParsePolyStr");
+BindGlobal("QDR_ParsePolyStr",
+ function(F, str)
+ local func, new_str;
+ # make sure `str` only contains these characters
+ new_str := String(str); # copy
+ RemoveCharacters(new_str,"0123456789x*+-^");
+ if (Length(new_str) > 0) then
+ ERROR("QDR_ParsePolyStr: invalid character(s) [",new_str,"] in polynomial ",str);
+ fi;
+
+ func := EvalString(Concatenation("""
+ function(F)
+ local x;
+ x := Indeterminate(F,"x");
+ return """, str, """;
+ end
+ """));
+ return func(F);
+ end);
+
#! @Description Create a header string describing the field `F`
#! for use in the function `WriteMTXE`.
#! If `F` is a prime Galois field, just specify it:
-#! `% Field: GF(p)`
+#! @BeginCode
+#! % Field: GF(p)
+#! @EndCode
#! For an extension field $\mathop{\rm GF}(p^m)$ with $p$ prime and $m>1$, also give
#! the primitive polynomial **which should not contain any spaces**. For example,
-#! `% Field: GF(7^4) PrimitiveP(x): x^4-2*x^2-3*x+3`
+#! @BeginCode
+#! % Field: GF(7^4) PrimitiveP(x): x^4-2*x^2-3*x+3
+#! @EndCode
#! See Chapter for details.
#! @Returns the created header string
#! @Arguments F
-DeclareGlobalFunction("QDR_FieldHeaderStr");
-InstallGlobalFunction("QDR_FieldHeaderStr",
+#DeclareGlobalFunction("QDR_FieldHeaderStr");
+BindGlobal("QDR_FieldHeaderStr",
function(F) # field F
local p,m, poly,lis,i,j, b, str, out;
if not IsField(F) then
@@ -200,14 +276,13 @@ InstallGlobalFunction("QDR_FieldHeaderStr",
#! @Returns the list [Field, ConversionDegree, FormatIndex] (plus anything else we
#! may need in the future); the list is to be used as the second
#! parameter in `QDR_ProcEntry()`
-DeclareGlobalFunction("QDR_ProcessFieldHeader");
-InstallGlobalFunction("QDR_ProcessFieldHeader",
+#DeclareGlobalFunction("QDR_ProcessFieldHeader");
+BindGlobal("QDR_ProcessFieldHeader",
function(recs,optF)
- local m,F,Fp,poly,x,ic,is,a,x_global_val,
- x_bound,x_readonly;
+ local m,F,Fp,poly,x,ic,is,a;
if (Length(recs)>2 and recs[1][1]='%' and recs[2]="Field:") then
- F:=EvalString(recs[3]);
+ F:=QDR_ParseFieldStr(recs[3]);
if not IsField(F) then
Error("invalid input file field '",recs[3],"' given\n");
fi;
@@ -237,29 +312,17 @@ InstallGlobalFunction("QDR_ProcessFieldHeader",
fi;
ic:=1; is:=1; # set default conversion degree
if Length(recs)>3 then # analyze primitive polynomial
- if StartsWith(recs[4],"PrimitiveP") then
+ if StartsWith(recs[4],"PrimitiveP(x)") then
# process primitive polynomial here
if Length(recs)=4 then
Error("Polynomial must be separated by space(s) ",recs[4],"\n");
fi;
+ if not EndsWith(recs[4],"):") then
+ Error("Invalid entry ",recs[4],"\n");
+ fi;
- x_readonly:=false;
- if IsReadOnlyGlobal("x") then
- x_readonly:=true;
- MakeReadWriteGlobal("x");
- fi;
-
- x_bound:=false;
- if IsBoundGlobal("x") then
- x_global_val:=ValueGlobal("x");
- x_bound:=true;
- UnbindGlobal("x");
- fi;
-
- BindGlobal("x",Indeterminate(F,"x"));
- poly:=EvalString(recs[5]);
+ poly:=QDR_ParsePolyStr(recs[5]);
- # Print("'",recs[5],"'=",poly,"\n");
if not IsUnivariatePolynomial(poly) then
Error("Univariate polynomial expected ",recs[5],"\n");
fi;
@@ -281,17 +344,6 @@ InstallGlobalFunction("QDR_ProcessFieldHeader",
is:= 1/ic mod (Size(F)-1);
Unbind(poly);
- MakeReadWriteGlobal("x");
- UnbindGlobal("x");
- if x_bound then
- BindGlobal("x",x_global_val);
- MakeReadWriteGlobal("x");
- x_bound:=false;
- fi;
- if x_readonly then
- MakeReadOnlyGlobal("x");
- fi;
-
fi;
fi;
@@ -319,8 +371,8 @@ InstallGlobalFunction("QDR_ProcessFieldHeader",
#!
#! @Returns the converted field element
#! @Arguments str, fmt, FileName, LineNo
-DeclareGlobalFunction("QDR_ProcEntry");
-InstallGlobalFunction("QDR_ProcEntry",
+#DeclareGlobalFunction("QDR_ProcEntry");
+BindGlobal("QDR_ProcEntry",
function(str,fmt,FileName,LineNo)
local ival, fval;
ival:=Int(str);
@@ -409,8 +461,8 @@ InstallGlobalFunction("QDR_ProcEntry",
#! of the group are represented depending on whether the field is a prime
#! field ($ q $ a prime) or an extension field with $ q=p^m $, $p$ prime, and $m>1$.
#!
-DeclareGlobalFunction("ReadMTXE");
-InstallGlobalFunction("ReadMTXE",
+#DeclareGlobalFunction("ReadMTXE");
+BindGlobal("ReadMTXE",
function(StrPath, opt... ) # supported option: "field"
local input, data, fmt, line, pair, F, rowsG, colsG, G, G1, i,
iCommentStart,iComment;
@@ -552,154 +604,154 @@ InstallGlobalFunction("ReadMTXE",
#! of the group are represented depending on whether the field is a prime
#! field ($ q $ a prime) or an extension field with $ q=p^m $, $ m>1 $.
#!
-DeclareGlobalFunction("WriteMTXE");
-InstallGlobalFunction("WriteMTXE", # function (StrPath,pair,G,comment...)
- function (StrPath,pair,G,comment...) # supported option: field [default: GF(2)]
- local F, dims, rows, cols, nonzero, i, row, pos, filename;
- # F - field to be used (default: no field specified)
- # dims - dimensions of matrix G
- # rows and cols - number of rows and columns of the matrix G
- # nonzero - number of lines needed to store all nonzero elements of matrix with
- # pair parameter as given
- # i - for "for" loop
- # i, row and pos - temporary variables
-
- # see if the field is specified
- if ValueOption("field")<>fail then
- if not IsField(ValueOption("field")) then
- Error("invalid option 'field'=",ValueOption("field"),"\n");
- else # default field is specified
- F:=ValueOption("field");
- fi;
- else
- F:=GF(2); # default
- fi;
-
- # We check pair parameter
- if (pair <0 ) or (pair>3) or (pair=2) then
- Error("\n", "Parameter pair=",pair," not supported, must be in {0,1,3}", "\n");
- fi;
-
- # full file name with extension
- if EndsWith(UppercaseString(StrPath),".MTX") then
- filename:=StrPath;
- else
- filename := Concatenation(StrPath, ".mtx");
- fi;
-
- if (pair=3) then row:="complex"; else row:="integer"; fi;
-
- # Header of the MatrixMarket
- PrintTo(filename, "%%MatrixMarket matrix coordinate ", row, " general", "\n");
- if ValueOption("field")<>fail then AppendTo(filename,QDR_FieldHeaderStr(F), "\n"); fi;
-
- for i in [1..Length(comment)] do
- if comment[i,1]<>'%' then
- AppendTo(filename, "% ", comment[i], "\n");
- else
- AppendTo(filename, comment[i], "\n");
- fi;
- od;
- if IsPrime(Size(F)) then
- AppendTo(filename,"% Values Z(",Size(F),") are given\n");
- else
- AppendTo(filename,"% Powers of GF(",Size(F),") primitive element and -1 for Zero are given\n");
- fi;
-
- # Matrix dimensions
- dims := DimensionsMat(G);;
- rows := dims[1];;
- cols := dims[2];;
-
- # count non-zero elements depending on the 'pair' parameter
- nonzero := 0;
- if (pair = 3) then
- for i in [1..rows] do
- nonzero := nonzero + QDR_SymplVecWeight(G[i], F);;
- od;
- else
- for i in [1..rows] do
- nonzero := nonzero + WeightVecFFE(G[i]);;
- od;
- fi;
-
- if (pair < 3) then
- # write dimensions of the matrix and number of line containing nonzero elements
- AppendTo(filename, rows, " ", cols, " ", nonzero, "\n");
-
- # Finally, write nonzero elements and their positions according to pair parameter and field F.
- if IsPrime(Size(F)) then # this includes binary field
- for i in [1..rows] do
- row := G[i];;
-
- pos := PositionNonZero(row, 0);;
- while pos <= cols do
- AppendTo(filename, i, " ", pos, " ", Int(row[pos]), "\n");
- pos := PositionNonZero(row, pos);;
- od;
- od;
- else # extension field
- for i in [1..rows] do
- row := G[i];;
-
- pos := PositionNonZero(row, 0);;
- while pos <= cols do
- AppendTo(filename, i, " ", pos, " ",
- LogFFE(row[pos], PrimitiveElement(F)), "\n");
- pos := PositionNonZero(row, pos);;
- od;
- od;
- fi;
- else # pair=3
- # write dimensions of the matrix and number of line containing nonzero elements
- AppendTo(filename, rows, " ", cols/2," ", nonzero, "\n");
- # Finally, write nonzero elements and their positions according to pair parameter and field F.
- if IsPrime(Size(F)) then
- for i in [1..rows] do
- row := G[i];;
- pos := PositionNonZero(row, 0);;
- while pos <= cols do
- # For Ai = 0
- if IsInt(pos/2) then
- AppendTo(filename, i, " ", pos/2, " ", 0, " ", Int(row[pos]), "\n");
- pos := PositionNonZero(row, pos);;
- # For Ai != 0
- else
- AppendTo(filename, i, " ", (pos+1)/2, " ", Int(row[pos]), " ", Int(row[pos + 1]), "\n");
- pos := PositionNonZero(row, pos + 1);;
- fi;
- od;
- od;
- else # extension field
- for i in [1..rows] do
- row := G[i];;
-
- pos := PositionNonZero(row, 0);;
- while pos <= cols do
- # For Ai = 0
- if IsInt(pos/2) then
- AppendTo(filename, i, " ", pos/2, " ", -1, " ", LogFFE(row[pos], PrimitiveElement(F)), "\n");
- pos := PositionNonZero(row, pos);;
- # For Ai != 0
- else
- # Check if Bi = 0
- if (row[pos + 1] = Zero(F)) then
- AppendTo(filename, i, " ", (pos+1)/2, " ", LogFFE(row[pos], PrimitiveElement(F)), " ", -1, "\n");
- else
- AppendTo(filename, i, " ", (pos+1)/2, " ", LogFFE(row[pos], PrimitiveElement(F)),
- " ", LogFFE(row[pos + 1], PrimitiveElement(F)), "\n");
- fi;
-
- pos := PositionNonZero(row, pos + 1);;
- fi;
- od;
- od;
- fi;
- fi;
-
- Print("File ", filename, " was created\n");
- end
- );
+#DeclareGlobalFunction("WriteMTXE");
+BindGlobal("WriteMTXE", # function (StrPath,pair,G,comment...)
+ function (StrPath,pair,G,comment...) # supported option: field [default: GF(2)]
+ local F, dims, rows, cols, nonzero, i, row, pos, filename;
+ # F - field to be used (default: no field specified)
+ # dims - dimensions of matrix G
+ # rows and cols - number of rows and columns of the matrix G
+ # nonzero - number of lines needed to store all nonzero elements of matrix with
+ # pair parameter as given
+ # i - for "for" loop
+ # i, row and pos - temporary variables
+
+ # see if the field is specified
+ if ValueOption("field")<>fail then
+ if not IsField(ValueOption("field")) then
+ Error("invalid option 'field'=",ValueOption("field"),"\n");
+ else # default field is specified
+ F:=ValueOption("field");
+ fi;
+ else
+ F:=GF(2); # default
+ fi;
+
+ # We check pair parameter
+ if (pair <0 ) or (pair>3) or (pair=2) then
+ Error("\n", "Parameter pair=",pair," not supported, must be in {0,1,3}", "\n");
+ fi;
+
+ # full file name with extension
+ if EndsWith(UppercaseString(StrPath),".MTX") then
+ filename:=StrPath;
+ else
+ filename := Concatenation(StrPath, ".mtx");
+ fi;
+
+ if (pair=3) then row:="complex"; else row:="integer"; fi;
+
+ # Header of the MatrixMarket
+ PrintTo(filename, "%%MatrixMarket matrix coordinate ", row, " general", "\n");
+ if ValueOption("field")<>fail then AppendTo(filename,QDR_FieldHeaderStr(F), "\n"); fi;
+
+ for i in [1..Length(comment)] do
+ if comment[i,1]<>'%' then
+ AppendTo(filename, "% ", comment[i], "\n");
+ else
+ AppendTo(filename, comment[i], "\n");
+ fi;
+ od;
+ if IsPrime(Size(F)) then
+ AppendTo(filename,"% Values Z(",Size(F),") are given\n");
+ else
+ AppendTo(filename,"% Powers of GF(",Size(F),") primitive element and -1 for Zero are given\n");
+ fi;
+
+ # Matrix dimensions
+ dims := DimensionsMat(G);;
+ rows := dims[1];;
+ cols := dims[2];;
+
+ # count non-zero elements depending on the 'pair' parameter
+ nonzero := 0;
+ if (pair = 3) then
+ for i in [1..rows] do
+ nonzero := nonzero + QDR_SymplVecWeight(G[i], F);;
+ od;
+ else
+ for i in [1..rows] do
+ nonzero := nonzero + WeightVecFFE(G[i]);;
+ od;
+ fi;
+
+ if (pair < 3) then
+ # write dimensions of the matrix and number of line containing nonzero elements
+ AppendTo(filename, rows, " ", cols, " ", nonzero, "\n");
+
+ # Finally, write nonzero elements and their positions according to pair parameter and field F.
+ if IsPrime(Size(F)) then # this includes binary field
+ for i in [1..rows] do
+ row := G[i];;
+
+ pos := PositionNonZero(row, 0);;
+ while pos <= cols do
+ AppendTo(filename, i, " ", pos, " ", Int(row[pos]), "\n");
+ pos := PositionNonZero(row, pos);;
+ od;
+ od;
+ else # extension field
+ for i in [1..rows] do
+ row := G[i];;
+
+ pos := PositionNonZero(row, 0);;
+ while pos <= cols do
+ AppendTo(filename, i, " ", pos, " ",
+ LogFFE(row[pos], PrimitiveElement(F)), "\n");
+ pos := PositionNonZero(row, pos);;
+ od;
+ od;
+ fi;
+ else # pair=3
+ # write dimensions of the matrix and number of line containing nonzero elements
+ AppendTo(filename, rows, " ", cols/2," ", nonzero, "\n");
+ # Finally, write nonzero elements and their positions according to pair parameter and field F.
+ if IsPrime(Size(F)) then
+ for i in [1..rows] do
+ row := G[i];;
+ pos := PositionNonZero(row, 0);;
+ while pos <= cols do
+ # For Ai = 0
+ if IsInt(pos/2) then
+ AppendTo(filename, i, " ", pos/2, " ", 0, " ", Int(row[pos]), "\n");
+ pos := PositionNonZero(row, pos);;
+ # For Ai != 0
+ else
+ AppendTo(filename, i, " ", (pos+1)/2, " ", Int(row[pos]), " ", Int(row[pos + 1]), "\n");
+ pos := PositionNonZero(row, pos + 1);;
+ fi;
+ od;
+ od;
+ else # extension field
+ for i in [1..rows] do
+ row := G[i];;
+
+ pos := PositionNonZero(row, 0);;
+ while pos <= cols do
+ # For Ai = 0
+ if IsInt(pos/2) then
+ AppendTo(filename, i, " ", pos/2, " ", -1, " ", LogFFE(row[pos], PrimitiveElement(F)), "\n");
+ pos := PositionNonZero(row, pos);;
+ # For Ai != 0
+ else
+ # Check if Bi = 0
+ if (row[pos + 1] = Zero(F)) then
+ AppendTo(filename, i, " ", (pos+1)/2, " ", LogFFE(row[pos], PrimitiveElement(F)), " ", -1, "\n");
+ else
+ AppendTo(filename, i, " ", (pos+1)/2, " ", LogFFE(row[pos], PrimitiveElement(F)),
+ " ", LogFFE(row[pos + 1], PrimitiveElement(F)), "\n");
+ fi;
+
+ pos := PositionNonZero(row, pos + 1);;
+ fi;
+ od;
+ od;
+ fi;
+ fi;
+
+ Print("File ", filename, " was created\n");
+ end
+ );
#! @Section HelperFunctions
@@ -712,8 +764,8 @@ InstallGlobalFunction("WriteMTXE", # function (StrPath,pair,G,comment...)
#! The parity of the number of columns is verified.
#! @Returns `H` (the check matrix constructed)
#!
-DeclareGlobalFunction("QDR_MakeH");
-InstallGlobalFunction("QDR_MakeH",
+#DeclareGlobalFunction("QDR_MakeH");
+BindGlobal("QDR_MakeH",
function(G, F)
local dims, i, H;
@@ -762,8 +814,8 @@ InstallGlobalFunction("QDR_MakeH",
#! description of the algorithm.
#! @Arguments HX, HZ, num, mindist[, debug] :field:=GF(2), maxav:=fail
#! @Returns An upper bound on the CSS distance $d_Z$
-DeclareGlobalFunction("DistRandCSS");
-InstallGlobalFunction("DistRandCSS",
+#DeclareGlobalFunction("DistRandCSS");
+BindGlobal("DistRandCSS",
function (GX,GZ,num,mindist,opt...) # supported options: field, maxav
local DistBound, i, j, dimsWZ, rowsWZ, colsWZ, F, debug, pos, CodeWords, mult,
@@ -919,8 +971,8 @@ InstallGlobalFunction("DistRandCSS",
#! see Section . Not set by default.
#! @Arguments G, num, mindist[, debug] :field:=GF(2), maxav:=fail
#! @Returns An upper bound on the code distance $d$
-DeclareGlobalFunction("DistRandStab");
-InstallGlobalFunction("DistRandStab",
+#DeclareGlobalFunction("DistRandStab");
+BindGlobal("DistRandStab",
function(G,num,mindist,opt...) # supported options: field, maxav
local F, debug, CodeWords, mult, TempPos, dims, H, i, l, j, W, V, dimsW,
rows, cols, DistBound, FirstVecFound, VecCount, per, W1, W2, TempVec, TempWeight,maxav,
@@ -1117,23 +1169,23 @@ InstallGlobalFunction("DistRandStab",
#! constructs the corresponding `m` by 2`n` double circulant matrix
#! obtained by `m` repeated cyclic shifts of the coefficients' vector
#! by $s=2$ positions at a time.
-DeclareGlobalFunction("QDR_DoCirc");
-InstallGlobalFunction("QDR_DoCirc",
- function(poly,m,n,F)
- local v,perm,j,deg,mat;
- v:=CoefficientsOfUnivariatePolynomial(poly);
- # F:=DefaultField(v);
- deg:=Length(v);
- if (n>deg) then
- v:=Concatenation(v,ListWithIdenticalEntries(n-deg,0*One(F)));
- fi;
- mat:=[v];
- perm:=Concatenation([n],[1..n-1]);
- for j in [2..m] do
- v:=v{perm};
- v:=v{perm}; # this creates a quantum code
- Append(mat,[v]);
- od;
- return mat;
- end);
+#DeclareGlobalFunction("QDR_DoCirc");
+BindGlobal("QDR_DoCirc",
+ function(poly,m,n,F)
+ local v,perm,j,deg,mat;
+ v:=CoefficientsOfUnivariatePolynomial(poly);
+ # F:=DefaultField(v);
+ deg:=Length(v);
+ if (n>deg) then
+ v:=Concatenation(v,ListWithIdenticalEntries(n-deg,0*One(F)));
+ fi;
+ mat:=[v];
+ perm:=Concatenation([n],[1..n-1]);
+ for j in [2..m] do
+ v:=v{perm};
+ v:=v{perm}; # this creates a quantum code
+ Append(mat,[v]);
+ od;
+ return mat;
+ end);
diff --git a/tst/qdistrnd02.tst b/tst/qdistrnd02.tst
index 7c200d2..a99280a 100644
--- a/tst/qdistrnd02.tst
+++ b/tst/qdistrnd02.tst
@@ -29,11 +29,11 @@ gap> H:=One(F)*[[1,0, -1,0, 0,0, 0,0 ], # original Hx in odd positions
gap> DistRandStab(H,100,0,2 : field:=F);
2
-# doc/_Chapter_AllFunctions.xml:463-466
+# doc/_Chapter_AllFunctions.xml:486-489
gap> QDR_AverageCalc([2,3,4,5]);
3.5
-# doc/_Chapter_AllFunctions.xml:469-480
+# doc/_Chapter_AllFunctions.xml:492-503
gap> F:=GF(3);;
gap> x:=Indeterminate(F,"x");; poly:=One(F)*(1-x);;
gap> n:=5;;
@@ -45,5 +45,21 @@ gap> Display(mat);
. . . . . . 1 2 . .
. . . . . . . . 1 2
+# doc/_Chapter_AllFunctions.xml:507-518
+gap> QDR_ParseFieldStr("Z(5)");
+Z(5)
+gap> QDR_ParseFieldStr("Z(17)");
+Z(17)
+gap> QDR_ParseFieldStr("GF(5^2)");
+GF(5^2)
+gap> QDR_ParseFieldStr("GF(25)");
+GF(5^2)
+gap> QDR_ParseFieldStr("GF(125^2)");
+GF(5^6)
+
+# doc/_Chapter_AllFunctions.xml:521-524
+gap> QDR_ParsePolyStr(GF(25),"x^2+1");
+x^2+Z(5)^0
+
#
gap> STOP_TEST("qdistrnd02.tst", 1 );