aboutsummaryrefslogtreecommitdiff
path: root/src/algebra/ffhom.spad.pamphlet
diff options
context:
space:
mode:
Diffstat (limited to 'src/algebra/ffhom.spad.pamphlet')
-rw-r--r--src/algebra/ffhom.spad.pamphlet431
1 files changed, 431 insertions, 0 deletions
diff --git a/src/algebra/ffhom.spad.pamphlet b/src/algebra/ffhom.spad.pamphlet
new file mode 100644
index 00000000..50bf7ef1
--- /dev/null
+++ b/src/algebra/ffhom.spad.pamphlet
@@ -0,0 +1,431 @@
+\documentclass{article}
+\usepackage{axiom}
+\begin{document}
+\title{\$SPAD/src/algebra ffhom.spad}
+\author{Johannes Grabmeier, Alfred Scheerhorn}
+\maketitle
+\begin{abstract}
+\end{abstract}
+\eject
+\tableofcontents
+\eject
+\begin{verbatim}
+-- 28.01.93: AS and JG: setting of init? flag in
+-- functions initialize put at the
+-- end to avoid errors with interruption.
+-- 12.05.92 JG: long lines
+-- 17.02.92 AS: convertWRTdifferentDefPol12 and convertWRTdifferentDefPol21
+-- simplified.
+-- 17.02.92 AS: initialize() modified set up of basis change
+-- matrices between normal and polynomial rep.
+-- New version uses reducedQPowers and is more efficient.
+-- 24.07.92 JG: error messages improved
+\end{verbatim}
+\section{package FFHOM FiniteFieldHomomorphisms}
+<<package FFHOM FiniteFieldHomomorphisms>>=
+)abbrev package FFHOM FiniteFieldHomomorphisms
+++ Authors: J.Grabmeier, A.Scheerhorn
+++ Date Created: 26.03.1991
+++ Date Last Updated:
+++ Basic Operations:
+++ Related Constructors: FiniteFieldCategory, FiniteAlgebraicExtensionField
+++ Also See:
+++ AMS Classifications:
+++ Keywords: finite field, homomorphism, isomorphism
+++ References:
+++ R.Lidl, H.Niederreiter: Finite Field, Encycoldia of Mathematics and
+++ Its Applications, Vol. 20, Cambridge Univ. Press, 1983, ISBN 0 521 30240 4
+++ J. Grabmeier, A. Scheerhorn: Finite Fields in AXIOM.
+++ AXIOM Technical Report Series, ATR/5 NP2522.
+++ Description:
+++ FiniteFieldHomomorphisms(F1,GF,F2) exports coercion functions of
+++ elements between the fields {\em F1} and {\em F2}, which both must be
+++ finite simple algebraic extensions of the finite ground field {\em GF}.
+FiniteFieldHomomorphisms(F1,GF,F2): Exports == Implementation where
+ F1: FiniteAlgebraicExtensionField(GF)
+ GF: FiniteFieldCategory
+ F2: FiniteAlgebraicExtensionField(GF)
+ -- the homorphism can only convert elements w.r.t. the last extension .
+ -- Adding a function 'groundField()' which returns the groundfield of GF
+ -- as a variable of type FiniteFieldCategory in the new compiler, one
+ -- could build up 'convert' recursively to get an homomorphism w.r.t
+ -- the whole extension.
+
+ I ==> Integer
+ NNI ==> NonNegativeInteger
+ SI ==> SingleInteger
+ PI ==> PositiveInteger
+ SUP ==> SparseUnivariatePolynomial
+ M ==> Matrix GF
+ FFP ==> FiniteFieldExtensionByPolynomial
+ FFPOL2 ==> FiniteFieldPolynomialPackage2
+ FFPOLY ==> FiniteFieldPolynomialPackage
+ OUT ==> OutputForm
+
+ Exports ==> with
+
+ coerce: F1 -> F2
+ ++ coerce(x) is the homomorphic image of x from
+ ++ {\em F1} in {\em F2}. Thus {\em coerce} is a
+ ++ field homomorphism between the fields extensions
+ ++ {\em F1} and {\em F2} both over ground field {\em GF}
+ ++ (the second argument to the package).
+ ++ Error: if the extension degree of {\em F1} doesn't divide
+ ++ the extension degree of {\em F2}.
+ ++ Note that the other coercion function in the
+ ++ \spadtype{FiniteFieldHomomorphisms} is a left inverse.
+
+ coerce: F2 -> F1
+ ++ coerce(x) is the homomorphic image of x from
+ ++ {\em F2} in {\em F1}, where {\em coerce} is a
+ ++ field homomorphism between the fields extensions
+ ++ {\em F2} and {\em F1} both over ground field {\em GF}
+ ++ (the second argument to the package).
+ ++ Error: if the extension degree of {\em F2} doesn't divide
+ ++ the extension degree of {\em F1}.
+ ++ Note that the other coercion function in the
+ ++ \spadtype{FiniteFieldHomomorphisms} is a left inverse.
+ -- coerce(coerce(x:F1)@F2)@F1 = x and coerce(coerce(y:F2)@F1)@F2 = y
+
+ Implementation ==> add
+
+-- global variables ===================================================
+
+ degree1:NNI:= extensionDegree()$F1
+ degree2:NNI:= extensionDegree()$F2
+ -- the degrees of the last extension
+
+ -- a necessary condition for the one field being an subfield of
+ -- the other one is, that the respective extension degrees are
+ -- multiples
+ if max(degree1,degree2) rem min(degree1,degree2) ^= 0 then
+ error "FFHOM: one extension degree must divide the other one"
+
+ conMat1to2:M:= zero(degree2,degree1)$M
+ -- conversion Matix for the conversion direction F1 -> F2
+ conMat2to1:M:= zero(degree1,degree2)$M
+ -- conversion Matix for the conversion direction F2 -> F1
+
+ repType1:=representationType()$F1
+ repType2:=representationType()$F2
+ -- the representation types of the fields
+
+ init?:Boolean:=true
+ -- gets false after initialization
+
+ defPol1:=definingPolynomial()$F1
+ defPol2:=definingPolynomial()$F2
+ -- the defining polynomials of the fields
+
+
+-- functions ==========================================================
+
+
+ compare: (SUP GF,SUP GF) -> Boolean
+ -- compares two polynomials
+
+ convertWRTsameDefPol12: F1 -> F2
+ convertWRTsameDefPol21: F2 -> F1
+ -- homomorphism if the last extension of F1 and F2 was build up
+ -- using the same defining polynomials
+
+ convertWRTdifferentDefPol12: F1 -> F2
+ convertWRTdifferentDefPol21: F2 -> F1
+ -- homomorphism if the last extension of F1 and F2 was build up
+ -- with different defining polynomials
+
+ initialize: () -> Void
+ -- computes the conversion matrices
+
+ compare(g:(SUP GF),f:(SUP GF)) ==
+ degree(f)$(SUP GF) >$NNI degree(g)$(SUP GF) => true
+ degree(f)$(SUP GF) <$NNI degree(g)$(SUP GF) => false
+ equal:Integer:=0
+ for i in degree(f)$(SUP GF)..0 by -1 while equal=0 repeat
+ not zero?(coefficient(f,i)$(SUP GF))$GF and _
+ zero?(coefficient(g,i)$(SUP GF))$GF => equal:=1
+ not zero?(coefficient(g,i)$(SUP GF))$GF and _
+ zero?(coefficient(f,i)$(SUP GF))$GF => equal:=(-1)
+ (f1:=lookup(coefficient(f,i)$(SUP GF))$GF) >$PositiveInteger _
+ (g1:=lookup(coefficient(g,i)$(SUP GF))$GF) => equal:=1
+ f1 <$PositiveInteger g1 => equal:=(-1)
+ equal=1 => true
+ false
+
+ initialize() ==
+ -- 1) in the case of equal def. polynomials initialize is called only
+ -- if one of the rep. types is "normal" and the other one is "polynomial"
+ -- we have to compute the basis change matrix 'mat', which i-th
+ -- column are the coordinates of a**(q**i), the i-th component of
+ -- the normal basis ('a' the root of the def. polynomial and q the
+ -- size of the groundfield)
+ defPol1 =$(SUP GF) defPol2 =>
+ -- new code using reducedQPowers
+ mat:=zero(degree1,degree1)$M
+ arr:=reducedQPowers(defPol1)$FFPOLY(GF)
+ for i in 1..degree1 repeat
+ setColumn_!(mat,i,vectorise(arr.(i-1),degree1)$SUP(GF))$M
+ -- old code
+ -- here one of the representation types must be "normal"
+ --a:=basis()$FFP(GF,defPol1).2 -- the root of the def. polynomial
+ --setColumn_!(mat,1,coordinates(a)$FFP(GF,defPol1))$M
+ --for i in 2..degree1 repeat
+ -- a:= a **$FFP(GF,defPol1) size()$GF
+ -- setColumn_!(mat,i,coordinates(a)$FFP(GF,defPol1))$M
+ --for the direction "normal" -> "polynomial" we have to multiply the
+ -- coordinate vector of an element of the normal basis field with
+ -- the matrix 'mat'. In this case 'mat' is the correct conversion
+ -- matrix for the conversion of F1 to F2, its inverse the correct
+ -- inversion matrix for the conversion of F2 to F1
+ repType1 = "normal" => -- repType2 = "polynomial"
+ conMat1to2:=copy(mat)
+ conMat2to1:=copy(inverse(mat)$M :: M)
+ --we finish the function for one case, hence reset initialization flag
+ init? := false
+ void()$Void
+ -- print("'normal' <=> 'polynomial' matrices initialized"::OUT)
+ -- in the other case we have to change the matrices
+ -- repType2 = "normal" and repType1 = "polynomial"
+ conMat2to1:=copy(mat)
+ conMat1to2:=copy(inverse(mat)$M :: M)
+ -- print("'normal' <=> 'polynomial' matrices initialized"::OUT)
+ --we finish the function for one case, hence reset initialization flag
+ init? := false
+ void()$Void
+ -- 2) in the case of different def. polynomials we have to order the
+ -- fields to get the same isomorphism, if the package is called with
+ -- the fields F1 and F2 swapped.
+ dPbig:= defPol2
+ rTbig:= repType2
+ dPsmall:= defPol1
+ rTsmall:= repType1
+ degbig:=degree2
+ degsmall:=degree1
+ if compare(defPol2,defPol1) then
+ degsmall:=degree2
+ degbig:=degree1
+ dPbig:= defPol1
+ rTbig:= repType1
+ dPsmall:= defPol2
+ rTsmall:= repType2
+ -- 3) in every case we need a conversion between the polynomial
+ -- represented fields. Therefore we compute 'root' as a root of the
+ -- 'smaller' def. polynomial in the 'bigger' field.
+ -- We compute the matrix 'matsb', which i-th column are the coordinates
+ -- of the (i-1)-th power of root, i=1..degsmall. Multiplying a
+ -- coordinate vector of an element of the 'smaller' field by this
+ -- matrix, we got the coordinates of the corresponding element in the
+ -- 'bigger' field.
+ -- compute the root of dPsmall in the 'big' field
+ root:=rootOfIrreduciblePoly(dPsmall)$FFPOL2(FFP(GF,dPbig),GF)
+ -- set up matrix for polynomial conversion
+ matsb:=zero(degbig,degsmall)$M
+ qsetelt_!(matsb,1,1,1$GF)$M
+ a:=root
+ for i in 2..degsmall repeat
+ setColumn_!(matsb,i,coordinates(a)$FFP(GF,dPbig))$M
+ a := a *$FFP(GF,dPbig) root
+ -- the conversion from 'big' to 'small': we can't invert matsb
+ -- directly, because it has degbig rows and degsmall columns and
+ -- may be no square matrix. Therfore we construct a square matrix
+ -- mat from degsmall linear independent rows of matsb and invert it.
+ -- Now we get the conversion matrix 'matbs' for the conversion from
+ -- 'big' to 'small' by putting the columns of mat at the indices
+ -- of the linear independent rows of matsb to columns of matbs.
+ ra:I:=1 -- the rank
+ mat:M:=transpose(row(matsb,1))$M -- has already rank 1
+ rowind:I:=2
+ iVec:Vector I:=new(degsmall,1$I)$(Vector I)
+ while ra < degsmall repeat
+ if rank(vertConcat(mat,transpose(row(matsb,rowind))$M)$M)$M > ra then
+ mat:=vertConcat(mat,transpose(row(matsb,rowind))$M)$M
+ ra:=ra+1
+ iVec.ra := rowind
+ rowind:=rowind + 1
+ mat:=inverse(mat)$M :: M
+ matbs:=zero(degsmall,degbig)$M
+ for i in 1..degsmall repeat
+ setColumn_!(matbs,iVec.i,column(mat,i)$M)$M
+ -- print(matsb::OUT)
+ -- print(matbs::OUT)
+ -- 4) if the 'bigger' field is "normal" we have to compose the
+ -- polynomial conversion with a conversion from polynomial to normal
+ -- between the FFP(GF,dPbig) and FFNBP(GF,dPbig) the 'bigger'
+ -- field. Therefore we compute a conversion matrix 'mat' as in 1)
+ -- Multiplying with the inverse of 'mat' yields the desired
+ -- conversion from polynomial to normal. Multiplying this matrix by
+ -- the above computed 'matsb' we got the matrix for converting form
+ -- 'small polynomial' to 'big normal'.
+ -- set up matrix 'mat' for polynomial to normal
+ if rTbig = "normal" then
+ arr:=reducedQPowers(dPbig)$FFPOLY(GF)
+ mat:=zero(degbig,degbig)$M
+ for i in 1..degbig repeat
+ setColumn_!(mat,i,vectorise(arr.(i-1),degbig)$SUP(GF))$M
+ -- old code
+ --a:=basis()$FFP(GF,dPbig).2 -- the root of the def.Polynomial
+ --setColumn_!(mat,1,coordinates(a)$FFP(GF,dPbig))$M
+ --for i in 2..degbig repeat
+ -- a:= a **$FFP(GF,dPbig) size()$GF
+ -- setColumn_!(mat,i,coordinates(a)$FFP(GF,dPbig))$M
+ -- print(inverse(mat)$M::OUT)
+ matsb:= (inverse(mat)$M :: M) * matsb
+ -- print("inv *.."::OUT)
+ matbs:=matbs * mat
+ -- 5) if the 'smaller' field is "normal" we have first to convert
+ -- from 'small normal' to 'small polynomial', that is from
+ -- FFNBP(GF,dPsmall) to FFP(GF,dPsmall). Therefore we compute a
+ -- conversion matrix 'mat' as in 1). Multiplying with 'mat'
+ -- yields the desired conversion from normal to polynomial.
+ -- Multiplying the above computed 'matsb' with 'mat' we got the
+ -- matrix for converting form 'small normal' to 'big normal'.
+ -- set up matrix 'mat' for normal to polynomial
+ if rTsmall = "normal" then
+ arr:=reducedQPowers(dPsmall)$FFPOLY(GF)
+ mat:=zero(degsmall,degsmall)$M
+ for i in 1..degsmall repeat
+ setColumn_!(mat,i,vectorise(arr.(i-1),degsmall)$SUP(GF))$M
+ -- old code
+ --b:FFP(GF,dPsmall):=basis()$FFP(GF,dPsmall).2
+ --setColumn_!(mat,1,coordinates(b)$FFP(GF,dPsmall))$M
+ --for i in 2..degsmall repeat
+ -- b:= b **$FFP(GF,dPsmall) size()$GF
+ -- setColumn_!(mat,i,coordinates(b)$FFP(GF,dPsmall))$M
+ -- print(mat::OUT)
+ matsb:= matsb * mat
+ matbs:= (inverse(mat) :: M) * matbs
+ -- now 'matsb' is the corret conversion matrix for 'small' to 'big'
+ -- and 'matbs' the corret one for 'big' to 'small'.
+ -- depending on the above ordering the conversion matrices are
+ -- initialized
+ dPbig =$(SUP GF) defPol2 =>
+ conMat1to2 :=matsb
+ conMat2to1 :=matbs
+ -- print(conMat1to2::OUT)
+ -- print(conMat2to1::OUT)
+ -- print("conversion matrices initialized"::OUT)
+ --we finish the function for one case, hence reset initialization flag
+ init? := false
+ void()$Void
+ conMat1to2 :=matbs
+ conMat2to1 :=matsb
+ -- print(conMat1to2::OUT)
+ -- print(conMat2to1::OUT)
+ -- print("conversion matrices initialized"::OUT)
+ --we finish the function for one case, hence reset initialization flag
+ init? := false
+ void()$Void
+
+
+ coerce(x:F1) ==
+ inGroundField?(x)$F1 => retract(x)$F1 :: F2
+ -- if x is already in GF then we can use a simple coercion
+ defPol1 =$(SUP GF) defPol2 => convertWRTsameDefPol12(x)
+ convertWRTdifferentDefPol12(x)
+
+ convertWRTsameDefPol12(x:F1) ==
+ repType1 = repType2 => x pretend F2
+ -- same groundfields, same defining polynomials, same
+ -- representation types --> F1 = F2, x is already in F2
+ repType1 = "cyclic" =>
+ x = 0$F1 => 0$F2
+ -- the SI corresponding to the cyclic representation is the exponent of
+ -- the primitiveElement, therefore we exponentiate the primitiveElement
+ -- of F2 by it.
+ primitiveElement()$F2 **$F2 (x pretend SI)
+ repType2 = "cyclic" =>
+ x = 0$F1 => 0$F2
+ -- to get the exponent, we have to take the discrete logarithm of the
+ -- element in the given field.
+ (discreteLog(x)$F1 pretend SI) pretend F2
+ -- here one of the representation types is "normal"
+ if init? then initialize()
+ -- here a conversion matrix is necessary, (see initialize())
+ represents(conMat1to2 *$(Matrix GF) coordinates(x)$F1)$F2
+
+ convertWRTdifferentDefPol12(x:F1) ==
+ if init? then initialize()
+ -- if we want to convert into a 'smaller' field, we have to test,
+ -- whether the element is in the subfield of the 'bigger' field, which
+ -- corresponds to the 'smaller' field
+ if degree1 > degree2 then
+ if positiveRemainder(degree2,degree(x)$F1)^= 0 then
+ error "coerce: element doesn't belong to smaller field"
+ represents(conMat1to2 *$(Matrix GF) coordinates(x)$F1)$F2
+
+-- the three functions below equal the three functions above up to
+-- '1' exchanged by '2' in all domain and variable names
+
+
+ coerce(x:F2) ==
+ inGroundField?(x)$F2 => retract(x)$F2 :: F1
+ -- if x is already in GF then we can use a simple coercion
+ defPol1 =$(SUP GF) defPol2 => convertWRTsameDefPol21(x)
+ convertWRTdifferentDefPol21(x)
+
+ convertWRTsameDefPol21(x:F2) ==
+ repType1 = repType2 => x pretend F1
+ -- same groundfields, same defining polynomials,
+ -- same representation types --> F1 = F2, that is:
+ -- x is already in F1
+ repType2 = "cyclic" =>
+ x = 0$F2 => 0$F1
+ primitiveElement()$F1 **$F1 (x pretend SI)
+ repType1 = "cyclic" =>
+ x = 0$F2 => 0$F1
+ (discreteLog(x)$F2 pretend SI) pretend F1
+ -- here one of the representation types is "normal"
+ if init? then initialize()
+ represents(conMat2to1 *$(Matrix GF) coordinates(x)$F2)$F1
+
+ convertWRTdifferentDefPol21(x:F2) ==
+ if init? then initialize()
+ if degree2 > degree1 then
+ if positiveRemainder(degree1,degree(x)$F2)^= 0 then
+ error "coerce: element doesn't belong to smaller field"
+ represents(conMat2to1 *$(Matrix GF) coordinates(x)$F2)$F1
+
+@
+\section{License}
+<<license>>=
+--Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
+--All rights reserved.
+--
+--Redistribution and use in source and binary forms, with or without
+--modification, are permitted provided that the following conditions are
+--met:
+--
+-- - Redistributions of source code must retain the above copyright
+-- notice, this list of conditions and the following disclaimer.
+--
+-- - Redistributions in binary form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in
+-- the documentation and/or other materials provided with the
+-- distribution.
+--
+-- - Neither the name of The Numerical ALgorithms Group Ltd. nor the
+-- names of its contributors may be used to endorse or promote products
+-- derived from this software without specific prior written permission.
+--
+--THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+--IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+--TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+--PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+--OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+--EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+--PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+--PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+--LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+--NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+--SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+@
+<<*>>=
+<<license>>
+
+<<package FFHOM FiniteFieldHomomorphisms>>
+@
+\eject
+\begin{thebibliography}{99}
+\bibitem{1} nothing
+\end{thebibliography}
+\end{document}