aboutsummaryrefslogtreecommitdiff
path: root/src/algebra/intclos.spad.pamphlet
diff options
context:
space:
mode:
authordos-reis <gdr@axiomatics.org>2007-08-14 05:14:52 +0000
committerdos-reis <gdr@axiomatics.org>2007-08-14 05:14:52 +0000
commitab8cc85adde879fb963c94d15675783f2cf4b183 (patch)
treec202482327f474583b750b2c45dedfc4e4312b1d /src/algebra/intclos.spad.pamphlet
downloadopen-axiom-ab8cc85adde879fb963c94d15675783f2cf4b183.tar.gz
Initial population.
Diffstat (limited to 'src/algebra/intclos.spad.pamphlet')
-rw-r--r--src/algebra/intclos.spad.pamphlet816
1 files changed, 816 insertions, 0 deletions
diff --git a/src/algebra/intclos.spad.pamphlet b/src/algebra/intclos.spad.pamphlet
new file mode 100644
index 00000000..4470fc41
--- /dev/null
+++ b/src/algebra/intclos.spad.pamphlet
@@ -0,0 +1,816 @@
+\documentclass{article}
+\usepackage{axiom}
+\begin{document}
+\title{\$SPAD/src/algebra intclos.spad}
+\author{Victor Miller, Barry Trager, Clifton Williamson}
+\maketitle
+\begin{abstract}
+\end{abstract}
+\eject
+\tableofcontents
+\eject
+\section{package TRIMAT TriangularMatrixOperations}
+<<package TRIMAT TriangularMatrixOperations>>=
+)abbrev package TRIMAT TriangularMatrixOperations
+++ Fraction free inverses of triangular matrices
+++ Author: Victor Miller
+++ Date Created:
+++ Date Last Updated: 24 Jul 1990
+++ Keywords:
+++ Examples:
+++ References:
+++ Description:
+++ This package provides functions that compute "fraction-free"
+++ inverses of upper and lower triangular matrices over a integral
+++ domain. By "fraction-free inverses" we mean the following:
+++ given a matrix B with entries in R and an element d of R such that
+++ d * inv(B) also has entries in R, we return d * inv(B). Thus,
+++ it is not necessary to pass to the quotient field in any of our
+++ computations.
+
+
+TriangularMatrixOperations(R,Row,Col,M): Exports == Implementation where
+ R : IntegralDomain
+ Row : FiniteLinearAggregate R
+ Col : FiniteLinearAggregate R
+ M : MatrixCategory(R,Row,Col)
+
+ Exports ==> with
+
+ UpTriBddDenomInv: (M,R) -> M
+ ++ UpTriBddDenomInv(B,d) returns M, where
+ ++ B is a non-singular upper triangular matrix and d is an
+ ++ element of R such that \spad{M = d * inv(B)} has entries in R.
+ LowTriBddDenomInv:(M,R) -> M
+ ++ LowTriBddDenomInv(B,d) returns M, where
+ ++ B is a non-singular lower triangular matrix and d is an
+ ++ element of R such that \spad{M = d * inv(B)} has entries in R.
+
+ Implementation ==> add
+
+ UpTriBddDenomInv(A,denom) ==
+ AI := zero(nrows A, nrows A)$M
+ offset := minColIndex AI - minRowIndex AI
+ for i in minRowIndex AI .. maxRowIndex AI
+ for j in minColIndex AI .. maxColIndex AI repeat
+ qsetelt_!(AI,i,j,(denom exquo qelt(A,i,j))::R)
+ for i in minRowIndex AI .. maxRowIndex AI repeat
+ for j in offset + i + 1 .. maxColIndex AI repeat
+ qsetelt_!(AI,i,j, - (((+/[qelt(AI,i,k) * qelt(A,k-offset,j)
+ for k in i+offset..(j-1)])
+ exquo qelt(A, j-offset, j))::R))
+ AI
+
+ LowTriBddDenomInv(A, denom) ==
+ AI := zero(nrows A, nrows A)$M
+ offset := minColIndex AI - minRowIndex AI
+ for i in minRowIndex AI .. maxRowIndex AI
+ for j in minColIndex AI .. maxColIndex AI repeat
+ qsetelt_!(AI,i,j,(denom exquo qelt(A,i,j))::R)
+ for i in minColIndex AI .. maxColIndex AI repeat
+ for j in i - offset + 1 .. maxRowIndex AI repeat
+ qsetelt_!(AI,j,i, - (((+/[qelt(A,j,k+offset) * qelt(AI,k,i)
+ for k in i-offset..(j-1)])
+ exquo qelt(A, j, j+offset))::R))
+ AI
+
+@
+\section{package IBATOOL IntegralBasisTools}
+<<package IBATOOL IntegralBasisTools>>=
+)abbrev package IBATOOL IntegralBasisTools
+++ Functions common to both integral basis packages
+++ Author: Victor Miller, Barry Trager, Clifton Williamson
+++ Date Created: 11 April 1990
+++ Date Last Updated: 20 September 1994
+++ Keywords: integral basis, function field, number field
+++ Examples:
+++ References:
+++ Description:
+++ This package contains functions used in the packages
+++ FunctionFieldIntegralBasis and NumberFieldIntegralBasis.
+
+IntegralBasisTools(R,UP,F): Exports == Implementation where
+ R : EuclideanDomain with
+ squareFree: $ -> Factored $
+ ++ squareFree(x) returns a square-free factorisation of x
+ UP : UnivariatePolynomialCategory R
+ F : FramedAlgebra(R,UP)
+ Mat ==> Matrix R
+ NNI ==> NonNegativeInteger
+ Ans ==> Record(basis: Mat, basisDen: R, basisInv:Mat)
+
+ Exports ==> with
+
+ diagonalProduct: Mat -> R
+ ++ diagonalProduct(m) returns the product of the elements on the
+ ++ diagonal of the matrix m
+ matrixGcd: (Mat,R,NNI) -> R
+ ++ matrixGcd(mat,sing,n) is \spad{gcd(sing,g)} where \spad{g} is the
+ ++ gcd of the entries of the \spad{n}-by-\spad{n} upper-triangular
+ ++ matrix \spad{mat}.
+ divideIfCan_!: (Matrix R,Matrix R,R,Integer) -> R
+ ++ divideIfCan!(matrix,matrixOut,prime,n) attempts to divide the
+ ++ entries of \spad{matrix} by \spad{prime} and store the result in
+ ++ \spad{matrixOut}. If it is successful, 1 is returned and if not,
+ ++ \spad{prime} is returned. Here both \spad{matrix} and
+ ++ \spad{matrixOut} are \spad{n}-by-\spad{n} upper triangular matrices.
+ leastPower: (NNI,NNI) -> NNI
+ ++ leastPower(p,n) returns e, where e is the smallest integer
+ ++ such that \spad{p **e >= n}
+ idealiser: (Mat,Mat) -> Mat
+ ++ idealiser(m1,m2) computes the order of an ideal defined by m1 and m2
+ idealiser: (Mat,Mat,R) -> Mat
+ ++ idealiser(m1,m2,d) computes the order of an ideal defined by m1 and m2
+ ++ where d is the known part of the denominator
+ idealiserMatrix: (Mat, Mat) -> Mat
+ ++ idealiserMatrix(m1, m2) returns the matrix representing the linear
+ ++ conditions on the Ring associatied with an ideal defined by m1 and m2.
+ moduleSum: (Ans,Ans) -> Ans
+ ++ moduleSum(m1,m2) returns the sum of two modules in the framed
+ ++ algebra \spad{F}. Each module \spad{mi} is represented as follows:
+ ++ F is a framed algebra with R-module basis \spad{w1,w2,...,wn} and
+ ++ \spad{mi} is a record \spad{[basis,basisDen,basisInv]}. If
+ ++ \spad{basis} is the matrix \spad{(aij, i = 1..n, j = 1..n)}, then
+ ++ a basis \spad{v1,...,vn} for \spad{mi} is given by
+ ++ \spad{vi = (1/basisDen) * sum(aij * wj, j = 1..n)}, i.e. the
+ ++ \spad{i}th row of 'basis' contains the coordinates of the
+ ++ \spad{i}th basis vector. Similarly, the \spad{i}th row of the
+ ++ matrix \spad{basisInv} contains the coordinates of \spad{wi} with
+ ++ respect to the basis \spad{v1,...,vn}: if \spad{basisInv} is the
+ ++ matrix \spad{(bij, i = 1..n, j = 1..n)}, then
+ ++ \spad{wi = sum(bij * vj, j = 1..n)}.
+
+ Implementation ==> add
+ import ModularHermitianRowReduction(R)
+ import TriangularMatrixOperations(R, Vector R, Vector R, Matrix R)
+
+ diagonalProduct m ==
+ ans : R := 1
+ for i in minRowIndex m .. maxRowIndex m
+ for j in minColIndex m .. maxColIndex m repeat
+ ans := ans * qelt(m, i, j)
+ ans
+
+ matrixGcd(mat,sing,n) ==
+ -- note: 'matrix' is upper triangular;
+ -- no need to do anything below the diagonal
+ d := sing
+ for i in 1..n repeat
+ for j in i..n repeat
+ if not zero?(mij := qelt(mat,i,j)) then d := gcd(d,mij)
+-- one? d => return d
+ (d = 1) => return d
+ d
+
+ divideIfCan_!(matrix,matrixOut,prime,n) ==
+ -- note: both 'matrix' and 'matrixOut' will be upper triangular;
+ -- no need to do anything below the diagonal
+ for i in 1..n repeat
+ for j in i..n repeat
+ (a := (qelt(matrix,i,j) exquo prime)) case "failed" => return prime
+ qsetelt_!(matrixOut,i,j,a :: R)
+ 1
+
+ leastPower(p,n) ==
+ -- efficiency is not an issue here
+ e : NNI := 1; q := p
+ while q < n repeat (e := e + 1; q := q * p)
+ e
+
+ idealiserMatrix(ideal,idealinv) ==
+ -- computes the Order of the ideal
+ n := rank()$F
+ bigm := zero(n * n,n)$Mat
+ mr := minRowIndex bigm; mc := minColIndex bigm
+ v := basis()$F
+ for i in 0..n-1 repeat
+ r := regularRepresentation qelt(v,i + minIndex v)
+ m := ideal * r * idealinv
+ for j in 0..n-1 repeat
+ for k in 0..n-1 repeat
+ bigm(j * n + k + mr,i + mc) := qelt(m,j + mr,k + mc)
+ bigm
+
+ idealiser(ideal,idealinv) ==
+ bigm := idealiserMatrix(ideal, idealinv)
+ transpose squareTop rowEch bigm
+
+ idealiser(ideal,idealinv,denom) ==
+ bigm := (idealiserMatrix(ideal, idealinv) exquo denom)::Mat
+ transpose squareTop rowEchelon(bigm,denom)
+
+ moduleSum(mod1,mod2) ==
+ rb1 := mod1.basis; rbden1 := mod1.basisDen; rbinv1 := mod1.basisInv
+ rb2 := mod2.basis; rbden2 := mod2.basisDen; rbinv2 := mod2.basisInv
+ -- compatibility check: doesn't take much computation time
+ (not square? rb1) or (not square? rbinv1) or (not square? rb2) _
+ or (not square? rbinv2) =>
+ error "moduleSum: matrices must be square"
+ ((n := nrows rb1) ^= (nrows rbinv1)) or (n ^= (nrows rb2)) _
+ or (n ^= (nrows rbinv2)) =>
+ error "moduleSum: matrices of imcompatible dimensions"
+ (zero? rbden1) or (zero? rbden2) =>
+ error "moduleSum: denominator must be non-zero"
+ den := lcm(rbden1,rbden2); c1 := den quo rbden1; c2 := den quo rbden2
+ rb := squareTop rowEchelon(vertConcat(c1 * rb1,c2 * rb2),den)
+ rbinv := UpTriBddDenomInv(rb,den)
+ [rb,den,rbinv]
+
+@
+\section{package FFINTBAS FunctionFieldIntegralBasis}
+<<package FFINTBAS FunctionFieldIntegralBasis>>=
+)abbrev package FFINTBAS FunctionFieldIntegralBasis
+++ Integral bases for function fields of dimension one
+++ Author: Victor Miller
+++ Date Created: 9 April 1990
+++ Date Last Updated: 20 September 1994
+++ Keywords:
+++ Examples:
+++ References:
+++ Description:
+++ In this package R is a Euclidean domain and F is a framed algebra
+++ over R. The package provides functions to compute the integral
+++ closure of R in the quotient field of F. It is assumed that
+++ \spad{char(R/P) = char(R)} for any prime P of R. A typical instance of
+++ this is when \spad{R = K[x]} and F is a function field over R.
+
+
+FunctionFieldIntegralBasis(R,UP,F): Exports == Implementation where
+ R : EuclideanDomain with
+ squareFree: $ -> Factored $
+ ++ squareFree(x) returns a square-free factorisation of x
+ UP : UnivariatePolynomialCategory R
+ F : FramedAlgebra(R,UP)
+
+ I ==> Integer
+ Mat ==> Matrix R
+ NNI ==> NonNegativeInteger
+
+ Exports ==> with
+ integralBasis : () -> Record(basis: Mat, basisDen: R, basisInv:Mat)
+ ++ \spad{integralBasis()} returns a record
+ ++ \spad{[basis,basisDen,basisInv]} containing information regarding
+ ++ the integral closure of R in the quotient field of F, where
+ ++ F is a framed algebra with R-module basis \spad{w1,w2,...,wn}.
+ ++ If \spad{basis} is the matrix \spad{(aij, i = 1..n, j = 1..n)}, then
+ ++ the \spad{i}th element of the integral basis is
+ ++ \spad{vi = (1/basisDen) * sum(aij * wj, j = 1..n)}, i.e. the
+ ++ \spad{i}th row of \spad{basis} contains the coordinates of the
+ ++ \spad{i}th basis vector. Similarly, the \spad{i}th row of the
+ ++ matrix \spad{basisInv} contains the coordinates of \spad{wi} with
+ ++ respect to the basis \spad{v1,...,vn}: if \spad{basisInv} is the
+ ++ matrix \spad{(bij, i = 1..n, j = 1..n)}, then
+ ++ \spad{wi = sum(bij * vj, j = 1..n)}.
+ localIntegralBasis : R -> Record(basis: Mat, basisDen: R, basisInv:Mat)
+ ++ \spad{integralBasis(p)} returns a record
+ ++ \spad{[basis,basisDen,basisInv]} containing information regarding
+ ++ the local integral closure of R at the prime \spad{p} in the quotient
+ ++ field of F, where F is a framed algebra with R-module basis
+ ++ \spad{w1,w2,...,wn}.
+ ++ If \spad{basis} is the matrix \spad{(aij, i = 1..n, j = 1..n)}, then
+ ++ the \spad{i}th element of the local integral basis is
+ ++ \spad{vi = (1/basisDen) * sum(aij * wj, j = 1..n)}, i.e. the
+ ++ \spad{i}th row of \spad{basis} contains the coordinates of the
+ ++ \spad{i}th basis vector. Similarly, the \spad{i}th row of the
+ ++ matrix \spad{basisInv} contains the coordinates of \spad{wi} with
+ ++ respect to the basis \spad{v1,...,vn}: if \spad{basisInv} is the
+ ++ matrix \spad{(bij, i = 1..n, j = 1..n)}, then
+ ++ \spad{wi = sum(bij * vj, j = 1..n)}.
+
+ Implementation ==> add
+ import IntegralBasisTools(R, UP, F)
+ import ModularHermitianRowReduction(R)
+ import TriangularMatrixOperations(R, Vector R, Vector R, Matrix R)
+
+ squaredFactors: R -> R
+ squaredFactors px ==
+ */[(if ffe.exponent > 1 then ffe.factor else 1$R)
+ for ffe in factors squareFree px]
+
+ iIntegralBasis: (Mat,R,R) -> Record(basis: Mat, basisDen: R, basisInv:Mat)
+ iIntegralBasis(tfm,disc,sing) ==
+ -- tfm = trace matrix of current order
+ n := rank()$F; tfm0 := copy tfm; disc0 := disc
+ rb := scalarMatrix(n, 1); rbinv := scalarMatrix(n, 1)
+ -- rb = basis matrix of current order
+ -- rbinv = inverse basis matrix of current order
+ -- these are wrt the original basis for F
+ rbden : R := 1; index : R := 1; oldIndex : R := 1
+ -- rbden = denominator for current basis matrix
+ -- index = index of original order in current order
+ not sizeLess?(1, sing) => [rb, rbden, rbinv]
+ repeat
+ -- compute the p-radical
+ idinv := transpose squareTop rowEchelon(tfm, sing)
+ -- [u1,..,un] are the coordinates of an element of the p-radical
+ -- iff [u1,..,un] * idinv is in sing * R^n
+ id := rowEchelon LowTriBddDenomInv(idinv, sing)
+ -- id = basis matrix of the p-radical
+ idinv := UpTriBddDenomInv(id, sing)
+ -- id * idinv = sing * identity
+ -- no need to check for inseparability in this case
+ rbinv := idealiser(id * rb, rbinv * idinv, sing * rbden)
+ index := diagonalProduct rbinv
+ rb := rowEchelon LowTriBddDenomInv(rbinv, rbden * sing)
+ g := matrixGcd(rb,sing,n)
+ if sizeLess?(1,g) then rb := (rb exquo g) :: Mat
+ rbden := rbden * (sing quo g)
+ rbinv := UpTriBddDenomInv(rb, rbden)
+ disc := disc0 quo (index * index)
+ indexChange := index quo oldIndex; oldIndex := index
+ sing := gcd(indexChange, squaredFactors disc)
+ not sizeLess?(1, sing) => return [rb, rbden, rbinv]
+ tfm := ((rb * tfm0 * transpose rb) exquo (rbden * rbden)) :: Mat
+
+ integralBasis() ==
+ n := rank()$F; p := characteristic()$F
+ (not zero? p) and (n >= p) =>
+ error "integralBasis: possible wild ramification"
+ tfm := traceMatrix()$F; disc := determinant tfm
+ sing := squaredFactors disc -- singularities of relative Spec
+ iIntegralBasis(tfm,disc,sing)
+
+ localIntegralBasis prime ==
+ n := rank()$F; p := characteristic()$F
+ (not zero? p) and (n >= p) =>
+ error "integralBasis: possible wild ramification"
+ tfm := traceMatrix()$F; disc := determinant tfm
+ (disc exquo (prime * prime)) case "failed" =>
+ [scalarMatrix(n,1),1,scalarMatrix(n,1)]
+ iIntegralBasis(tfm,disc,prime)
+
+@
+\section{package WFFINTBS WildFunctionFieldIntegralBasis}
+<<package WFFINTBS WildFunctionFieldIntegralBasis>>=
+)abbrev package WFFINTBS WildFunctionFieldIntegralBasis
+++ Authors: Victor Miller, Clifton Williamson
+++ Date Created: 24 July 1991
+++ Date Last Updated: 20 September 1994
+++ Basic Operations: integralBasis, localIntegralBasis
+++ Related Domains: IntegralBasisTools(R,UP,F),
+++ TriangularMatrixOperations(R,Vector R,Vector R,Matrix R)
+++ Also See: FunctionFieldIntegralBasis, NumberFieldIntegralBasis
+++ AMS Classifications:
+++ Keywords: function field, integral basis
+++ Examples:
+++ References:
+++ Description:
+++ In this package K is a finite field, R is a ring of univariate
+++ polynomials over K, and F is a framed algebra over R. The package
+++ provides a function to compute the integral closure of R in the quotient
+++ field of F as well as a function to compute a "local integral basis"
+++ at a specific prime.
+
+WildFunctionFieldIntegralBasis(K,R,UP,F): Exports == Implementation where
+ K : FiniteFieldCategory
+ --K : Join(Field,Finite)
+ R : UnivariatePolynomialCategory K
+ UP : UnivariatePolynomialCategory R
+ F : FramedAlgebra(R,UP)
+
+ I ==> Integer
+ Mat ==> Matrix R
+ NNI ==> NonNegativeInteger
+ SAE ==> SimpleAlgebraicExtension
+ RResult ==> Record(basis: Mat, basisDen: R, basisInv:Mat)
+ IResult ==> Record(basis: Mat, basisDen: R, basisInv:Mat,discr: R)
+ MATSTOR ==> StorageEfficientMatrixOperations
+
+ Exports ==> with
+ integralBasis : () -> RResult
+ ++ \spad{integralBasis()} returns a record
+ ++ \spad{[basis,basisDen,basisInv]} containing information regarding
+ ++ the integral closure of R in the quotient field of F, where
+ ++ F is a framed algebra with R-module basis \spad{w1,w2,...,wn}.
+ ++ If \spad{basis} is the matrix \spad{(aij, i = 1..n, j = 1..n)}, then
+ ++ the \spad{i}th element of the integral basis is
+ ++ \spad{vi = (1/basisDen) * sum(aij * wj, j = 1..n)}, i.e. the
+ ++ \spad{i}th row of \spad{basis} contains the coordinates of the
+ ++ \spad{i}th basis vector. Similarly, the \spad{i}th row of the
+ ++ matrix \spad{basisInv} contains the coordinates of \spad{wi} with
+ ++ respect to the basis \spad{v1,...,vn}: if \spad{basisInv} is the
+ ++ matrix \spad{(bij, i = 1..n, j = 1..n)}, then
+ ++ \spad{wi = sum(bij * vj, j = 1..n)}.
+ localIntegralBasis : R -> RResult
+ ++ \spad{integralBasis(p)} returns a record
+ ++ \spad{[basis,basisDen,basisInv]} containing information regarding
+ ++ the local integral closure of R at the prime \spad{p} in the quotient
+ ++ field of F, where F is a framed algebra with R-module basis
+ ++ \spad{w1,w2,...,wn}.
+ ++ If \spad{basis} is the matrix \spad{(aij, i = 1..n, j = 1..n)}, then
+ ++ the \spad{i}th element of the local integral basis is
+ ++ \spad{vi = (1/basisDen) * sum(aij * wj, j = 1..n)}, i.e. the
+ ++ \spad{i}th row of \spad{basis} contains the coordinates of the
+ ++ \spad{i}th basis vector. Similarly, the \spad{i}th row of the
+ ++ matrix \spad{basisInv} contains the coordinates of \spad{wi} with
+ ++ respect to the basis \spad{v1,...,vn}: if \spad{basisInv} is the
+ ++ matrix \spad{(bij, i = 1..n, j = 1..n)}, then
+ ++ \spad{wi = sum(bij * vj, j = 1..n)}.
+
+ Implementation ==> add
+ import IntegralBasisTools(R, UP, F)
+ import ModularHermitianRowReduction(R)
+ import TriangularMatrixOperations(R, Vector R, Vector R, Matrix R)
+ import DistinctDegreeFactorize(K,R)
+
+ listSquaredFactors: R -> List R
+ listSquaredFactors px ==
+ -- returns a list of the factors of px which occur with
+ -- exponent > 1
+ ans : List R := empty()
+ factored := factor(px)$DistinctDegreeFactorize(K,R)
+ for f in factors(factored) repeat
+ if f.exponent > 1 then ans := concat(f.factor,ans)
+ ans
+
+ iLocalIntegralBasis: (Vector F,Vector F,Matrix R,Matrix R,R,R) -> IResult
+ iLocalIntegralBasis(bas,pows,tfm,matrixOut,disc,prime) ==
+ n := rank()$F; standardBasis := basis()$F
+ -- 'standardBasis' is the basis for F as a FramedAlgebra;
+ -- usually this is [1,y,y**2,...,y**(n-1)]
+ p2 := prime * prime; sae := SAE(K,R,prime)
+ p := characteristic()$F; q := size()$sae
+ lp := leastPower(q,n)
+ rb := scalarMatrix(n,1); rbinv := scalarMatrix(n,1)
+ -- rb = basis matrix of current order
+ -- rbinv = inverse basis matrix of current order
+ -- these are wrt the orginal basis for F
+ rbden : R := 1; index : R := 1; oldIndex : R := 1
+ -- rbden = denominator for current basis matrix
+ -- index = index of original order in current order
+ repeat
+ -- pows = [(w1 * rbden) ** q,...,(wn * rbden) ** q], where
+ -- bas = [w1,...,wn] is 'rbden' times the basis for the order B = 'rb'
+ for i in 1..n repeat
+ bi : F := 0
+ for j in 1..n repeat
+ bi := bi + qelt(rb,i,j) * qelt(standardBasis,j)
+ qsetelt_!(bas,i,bi)
+ qsetelt_!(pows,i,bi ** p)
+ coor0 := transpose coordinates(pows,bas)
+ denPow := rbden ** ((p - 1) :: NNI)
+ (coMat0 := coor0 exquo denPow) case "failed" =>
+ error "can't happen"
+ -- the jth column of coMat contains the coordinates of (wj/rbden)**q
+ -- with respect to the basis [w1/rbden,...,wn/rbden]
+ coMat := coMat0 :: Matrix R
+ -- the ith column of 'pPows' contains the coordinates of the pth power
+ -- of the ith basis element for B/prime.B over 'sae' = R/prime.R
+ pPows := map(reduce,coMat)$MatrixCategoryFunctions2(R,Vector R,
+ Vector R,Matrix R,sae,Vector sae,Vector sae,Matrix sae)
+ -- 'frob' will eventually be the Frobenius matrix for B/prime.B over
+ -- 'sae' = R/prime.R; at each stage of the loop the ith column will
+ -- contain the coordinates of p^k-th powers of the ith basis element
+ frob := copy pPows; tmpMat : Matrix sae := new(n,n,0)
+ for r in 2..leastPower(p,q) repeat
+ for i in 1..n repeat for j in 1..n repeat
+ qsetelt_!(tmpMat,i,j,qelt(frob,i,j) ** p)
+ times_!(frob,pPows,tmpMat)$MATSTOR(sae)
+ frobPow := frob ** lp
+ -- compute the p-radical
+ ns := nullSpace frobPow
+ for i in 1..n repeat for j in 1..n repeat qsetelt_!(tfm,i,j,0)
+ for vec in ns for i in 1.. repeat
+ for j in 1..n repeat
+ qsetelt_!(tfm,i,j,lift qelt(vec,j))
+ id := squareTop rowEchelon(tfm,prime)
+ -- id = basis matrix of the p-radical
+ idinv := UpTriBddDenomInv(id, prime)
+ -- id * idinv = prime * identity
+ -- no need to check for inseparability in this case
+ rbinv := idealiser(id * rb, rbinv * idinv, prime * rbden)
+ index := diagonalProduct rbinv
+ rb := rowEchelon LowTriBddDenomInv(rbinv,rbden * prime)
+ if divideIfCan_!(rb,matrixOut,prime,n) = 1
+ then rb := matrixOut
+ else rbden := rbden * prime
+ rbinv := UpTriBddDenomInv(rb,rbden)
+ indexChange := index quo oldIndex
+ oldIndex := index
+ disc := disc quo (indexChange * indexChange)
+ (not sizeLess?(1,indexChange)) or ((disc exquo p2) case "failed") =>
+ return [rb, rbden, rbinv, disc]
+
+ integralBasis() ==
+ traceMat := traceMatrix()$F; n := rank()$F
+ disc := determinant traceMat -- discriminant of current order
+ zero? disc => error "integralBasis: polynomial must be separable"
+ singList := listSquaredFactors disc -- singularities of relative Spec
+ runningRb := scalarMatrix(n,1); runningRbinv := scalarMatrix(n,1)
+ -- runningRb = basis matrix of current order
+ -- runningRbinv = inverse basis matrix of current order
+ -- these are wrt the original basis for F
+ runningRbden : R := 1
+ -- runningRbden = denominator for current basis matrix
+ empty? singList => [runningRb, runningRbden, runningRbinv]
+ bas : Vector F := new(n,0); pows : Vector F := new(n,0)
+ -- storage for basis elements and their powers
+ tfm : Matrix R := new(n,n,0)
+ -- 'tfm' will contain the coordinates of a lifting of the kernel
+ -- of a power of Frobenius
+ matrixOut : Matrix R := new(n,n,0)
+ for prime in singList repeat
+ lb := iLocalIntegralBasis(bas,pows,tfm,matrixOut,disc,prime)
+ rb := lb.basis; rbinv := lb.basisInv; rbden := lb.basisDen
+ disc := lb.discr
+ -- update 'running integral basis' if newly computed
+ -- local integral basis is non-trivial
+ if sizeLess?(1,rbden) then
+ mat := vertConcat(rbden * runningRb,runningRbden * rb)
+ runningRbden := runningRbden * rbden
+ runningRb := squareTop rowEchelon(mat,runningRbden)
+ runningRbinv := UpTriBddDenomInv(runningRb,runningRbden)
+ [runningRb, runningRbden, runningRbinv]
+
+ localIntegralBasis prime ==
+ traceMat := traceMatrix()$F; n := rank()$F
+ disc := determinant traceMat -- discriminant of current order
+ zero? disc => error "localIntegralBasis: polynomial must be separable"
+ (disc exquo (prime * prime)) case "failed" =>
+ [scalarMatrix(n,1), 1, scalarMatrix(n,1)]
+ bas : Vector F := new(n,0); pows : Vector F := new(n,0)
+ -- storage for basis elements and their powers
+ tfm : Matrix R := new(n,n,0)
+ -- 'tfm' will contain the coordinates of a lifting of the kernel
+ -- of a power of Frobenius
+ matrixOut : Matrix R := new(n,n,0)
+ lb := iLocalIntegralBasis(bas,pows,tfm,matrixOut,disc,prime)
+ [lb.basis, lb.basisDen, lb.basisInv]
+
+@
+\section{package NFINTBAS NumberFieldIntegralBasis}
+<<package NFINTBAS NumberFieldIntegralBasis>>=
+)abbrev package NFINTBAS NumberFieldIntegralBasis
+++ Author: Victor Miller, Clifton Williamson
+++ Date Created: 9 April 1990
+++ Date Last Updated: 20 September 1994
+++ Basic Operations: discriminant, integralBasis
+++ Related Domains: IntegralBasisTools, TriangularMatrixOperations
+++ Also See: FunctionFieldIntegralBasis, WildFunctionFieldIntegralBasis
+++ AMS Classifications:
+++ Keywords: number field, integral basis, discriminant
+++ Examples:
+++ References:
+++ Description:
+++ In this package F is a framed algebra over the integers (typically
+++ \spad{F = Z[a]} for some algebraic integer a). The package provides
+++ functions to compute the integral closure of Z in the quotient
+++ quotient field of F.
+NumberFieldIntegralBasis(UP,F): Exports == Implementation where
+ UP : UnivariatePolynomialCategory Integer
+ F : FramedAlgebra(Integer,UP)
+
+ FR ==> Factored Integer
+ I ==> Integer
+ Mat ==> Matrix I
+ NNI ==> NonNegativeInteger
+ Ans ==> Record(basis: Mat, basisDen: I, basisInv:Mat,discr: I)
+
+ Exports ==> with
+ discriminant: () -> Integer
+ ++ \spad{discriminant()} returns the discriminant of the integral
+ ++ closure of Z in the quotient field of the framed algebra F.
+ integralBasis : () -> Record(basis: Mat, basisDen: I, basisInv:Mat)
+ ++ \spad{integralBasis()} returns a record
+ ++ \spad{[basis,basisDen,basisInv]}
+ ++ containing information regarding the integral closure of Z in the
+ ++ quotient field of F, where F is a framed algebra with Z-module
+ ++ basis \spad{w1,w2,...,wn}.
+ ++ If \spad{basis} is the matrix \spad{(aij, i = 1..n, j = 1..n)}, then
+ ++ the \spad{i}th element of the integral basis is
+ ++ \spad{vi = (1/basisDen) * sum(aij * wj, j = 1..n)}, i.e. the
+ ++ \spad{i}th row of \spad{basis} contains the coordinates of the
+ ++ \spad{i}th basis vector. Similarly, the \spad{i}th row of the
+ ++ matrix \spad{basisInv} contains the coordinates of \spad{wi} with
+ ++ respect to the basis \spad{v1,...,vn}: if \spad{basisInv} is the
+ ++ matrix \spad{(bij, i = 1..n, j = 1..n)}, then
+ ++ \spad{wi = sum(bij * vj, j = 1..n)}.
+ localIntegralBasis : I -> Record(basis: Mat, basisDen: I, basisInv:Mat)
+ ++ \spad{integralBasis(p)} returns a record
+ ++ \spad{[basis,basisDen,basisInv]} containing information regarding
+ ++ the local integral closure of Z at the prime \spad{p} in the quotient
+ ++ field of F, where F is a framed algebra with Z-module basis
+ ++ \spad{w1,w2,...,wn}.
+ ++ If \spad{basis} is the matrix \spad{(aij, i = 1..n, j = 1..n)}, then
+ ++ the \spad{i}th element of the integral basis is
+ ++ \spad{vi = (1/basisDen) * sum(aij * wj, j = 1..n)}, i.e. the
+ ++ \spad{i}th row of \spad{basis} contains the coordinates of the
+ ++ \spad{i}th basis vector. Similarly, the \spad{i}th row of the
+ ++ matrix \spad{basisInv} contains the coordinates of \spad{wi} with
+ ++ respect to the basis \spad{v1,...,vn}: if \spad{basisInv} is the
+ ++ matrix \spad{(bij, i = 1..n, j = 1..n)}, then
+ ++ \spad{wi = sum(bij * vj, j = 1..n)}.
+
+ Implementation ==> add
+ import IntegralBasisTools(I, UP, F)
+ import ModularHermitianRowReduction(I)
+ import TriangularMatrixOperations(I, Vector I, Vector I, Matrix I)
+
+ frobMatrix : (Mat,Mat,I,NNI) -> Mat
+ wildPrimes : (FR,I) -> List I
+ tameProduct : (FR,I) -> I
+ iTameLocalIntegralBasis : (Mat,I,I) -> Ans
+ iWildLocalIntegralBasis : (Mat,I,I) -> Ans
+
+ frobMatrix(rb,rbinv,rbden,p) ==
+ n := rank()$F; b := basis()$F
+ v : Vector F := new(n,0)
+ for i in minIndex(v)..maxIndex(v)
+ for ii in minRowIndex(rb)..maxRowIndex(rb) repeat
+ a : F := 0
+ for j in minIndex(b)..maxIndex(b)
+ for jj in minColIndex(rb)..maxColIndex(rb) repeat
+ a := a + qelt(rb,ii,jj) * qelt(b,j)
+ qsetelt_!(v,i,a**p)
+ mat := transpose coordinates v
+ ((transpose(rbinv) * mat) exquo (rbden ** p)) :: Mat
+
+ wildPrimes(factoredDisc,n) ==
+ -- returns a list of the primes <=n which divide factoredDisc to a
+ -- power greater than 1
+ ans : List I := empty()
+ for f in factors(factoredDisc) repeat
+ if f.exponent > 1 and f.factor <= n then ans := concat(f.factor,ans)
+ ans
+
+ tameProduct(factoredDisc,n) ==
+ -- returns the product of the primes > n which divide factoredDisc
+ -- to a power greater than 1
+ ans : I := 1
+ for f in factors(factoredDisc) repeat
+ if f.exponent > 1 and f.factor > n then ans := f.factor * ans
+ ans
+
+ integralBasis() ==
+ traceMat := traceMatrix()$F; n := rank()$F
+ disc := determinant traceMat -- discriminant of current order
+ disc0 := disc -- this is disc(F)
+ factoredDisc := factor(disc0)$IntegerFactorizationPackage(Integer)
+ wilds := wildPrimes(factoredDisc,n)
+ sing := tameProduct(factoredDisc,n)
+ runningRb := scalarMatrix(n, 1); runningRbinv := scalarMatrix(n, 1)
+ -- runningRb = basis matrix of current order
+ -- runningRbinv = inverse basis matrix of current order
+ -- these are wrt the original basis for F
+ runningRbden : I := 1
+ -- runningRbden = denominator for current basis matrix
+-- one? sing and empty? wilds => [runningRb, runningRbden, runningRbinv]
+ (sing = 1) and empty? wilds => [runningRb, runningRbden, runningRbinv]
+ -- id = basis matrix of the ideal (p-radical) wrt current basis
+ matrixOut : Mat := scalarMatrix(n,0)
+ for p in wilds repeat
+ lb := iWildLocalIntegralBasis(matrixOut,disc,p)
+ rb := lb.basis; rbinv := lb.basisInv; rbden := lb.basisDen
+ disc := lb.discr
+ -- update 'running integral basis' if newly computed
+ -- local integral basis is non-trivial
+ if sizeLess?(1,rbden) then
+ mat := vertConcat(rbden * runningRb,runningRbden * rb)
+ runningRbden := runningRbden * rbden
+ runningRb := squareTop rowEchelon(mat,runningRbden)
+ runningRbinv := UpTriBddDenomInv(runningRb,runningRbden)
+ lb := iTameLocalIntegralBasis(traceMat,disc,sing)
+ rb := lb.basis; rbinv := lb.basisInv; rbden := lb.basisDen
+ disc := lb.discr
+ -- update 'running integral basis' if newly computed
+ -- local integral basis is non-trivial
+ if sizeLess?(1,rbden) then
+ mat := vertConcat(rbden * runningRb,runningRbden * rb)
+ runningRbden := runningRbden * rbden
+ runningRb := squareTop rowEchelon(mat,runningRbden)
+ runningRbinv := UpTriBddDenomInv(runningRb,runningRbden)
+ [runningRb,runningRbden,runningRbinv]
+
+ localIntegralBasis p ==
+ traceMat := traceMatrix()$F; n := rank()$F
+ disc := determinant traceMat -- discriminant of current order
+ (disc exquo (p*p)) case "failed" =>
+ [scalarMatrix(n, 1), 1, scalarMatrix(n, 1)]
+ lb :=
+ p > rank()$F =>
+ iTameLocalIntegralBasis(traceMat,disc,p)
+ iWildLocalIntegralBasis(scalarMatrix(n,0),disc,p)
+ [lb.basis,lb.basisDen,lb.basisInv]
+
+ iTameLocalIntegralBasis(traceMat,disc,sing) ==
+ n := rank()$F; disc0 := disc
+ rb := scalarMatrix(n, 1); rbinv := scalarMatrix(n, 1)
+ -- rb = basis matrix of current order
+ -- rbinv = inverse basis matrix of current order
+ -- these are wrt the original basis for F
+ rbden : I := 1; index : I := 1; oldIndex : I := 1
+ -- rbden = denominator for current basis matrix
+ -- id = basis matrix of the ideal (p-radical) wrt current basis
+ tfm := traceMat
+ repeat
+ -- compute the p-radical = p-trace-radical
+ idinv := transpose squareTop rowEchelon(tfm,sing)
+ -- [u1,..,un] are the coordinates of an element of the p-radical
+ -- iff [u1,..,un] * idinv is in p * Z^n
+ id := rowEchelon LowTriBddDenomInv(idinv, sing)
+ -- id = basis matrix of the p-radical
+ idinv := UpTriBddDenomInv(id, sing)
+ -- id * idinv = sing * identity
+ -- no need to check for inseparability in this case
+ rbinv := idealiser(id * rb, rbinv * idinv, sing * rbden)
+ index := diagonalProduct rbinv
+ rb := rowEchelon LowTriBddDenomInv(rbinv, sing * rbden)
+ g := matrixGcd(rb,sing,n)
+ if sizeLess?(1,g) then rb := (rb exquo g) :: Mat
+ rbden := rbden * (sing quo g)
+ rbinv := UpTriBddDenomInv(rb, rbden)
+ disc := disc0 quo (index * index)
+ indexChange := index quo oldIndex; oldIndex := index
+-- one? indexChange => return [rb, rbden, rbinv, disc]
+ (indexChange = 1) => return [rb, rbden, rbinv, disc]
+ tfm := ((rb * traceMat * transpose rb) exquo (rbden * rbden)) :: Mat
+
+ iWildLocalIntegralBasis(matrixOut,disc,p) ==
+ n := rank()$F; disc0 := disc
+ rb := scalarMatrix(n, 1); rbinv := scalarMatrix(n, 1)
+ -- rb = basis matrix of current order
+ -- rbinv = inverse basis matrix of current order
+ -- these are wrt the original basis for F
+ rbden : I := 1; index : I := 1; oldIndex : I := 1
+ -- rbden = denominator for current basis matrix
+ -- id = basis matrix of the ideal (p-radical) wrt current basis
+ p2 := p * p; lp := leastPower(p::NNI,n)
+ repeat
+ tfm := frobMatrix(rb,rbinv,rbden,p::NNI) ** lp
+ -- compute Rp = p-radical
+ idinv := transpose squareTop rowEchelon(tfm, p)
+ -- [u1,..,un] are the coordinates of an element of Rp
+ -- iff [u1,..,un] * idinv is in p * Z^n
+ id := rowEchelon LowTriBddDenomInv(idinv,p)
+ -- id = basis matrix of the p-radical
+ idinv := UpTriBddDenomInv(id,p)
+ -- id * idinv = p * identity
+ -- no need to check for inseparability in this case
+ rbinv := idealiser(id * rb, rbinv * idinv, p * rbden)
+ index := diagonalProduct rbinv
+ rb := rowEchelon LowTriBddDenomInv(rbinv, p * rbden)
+ if divideIfCan_!(rb,matrixOut,p,n) = 1
+ then rb := matrixOut
+ else rbden := p * rbden
+ rbinv := UpTriBddDenomInv(rb, rbden)
+ indexChange := index quo oldIndex; oldIndex := index
+ disc := disc quo (indexChange * indexChange)
+-- one? indexChange or gcd(p2,disc) ^= p2 =>
+ (indexChange = 1) or gcd(p2,disc) ^= p2 =>
+ return [rb, rbden, rbinv, disc]
+
+ discriminant() ==
+ disc := determinant traceMatrix()$F
+ intBas := integralBasis()
+ rb := intBas.basis; rbden := intBas.basisDen
+ index := ((rbden ** rank()$F) exquo (determinant rb)) :: Integer
+ (disc exquo (index * index)) :: Integer
+
+@
+\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 TRIMAT TriangularMatrixOperations>>
+<<package IBATOOL IntegralBasisTools>>
+<<package FFINTBAS FunctionFieldIntegralBasis>>
+<<package WFFINTBS WildFunctionFieldIntegralBasis>>
+<<package NFINTBAS NumberFieldIntegralBasis>>
+@
+\eject
+\begin{thebibliography}{99}
+\bibitem{1} nothing
+\end{thebibliography}
+\end{document}