/usr/share/axiom-20170501/src/algebra/FSPRMELT.spad is in axiom-source 20170501-3.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | )abbrev package FSPRMELT FunctionSpacePrimitiveElement
++ Author: Manuel Bronstein
++ Date Created: 6 Jun 1990
++ Date Last Updated: 25 April 1991
++ Description:
++ FunctionsSpacePrimitiveElement provides functions to compute
++ primitive elements in functions spaces;
FunctionSpacePrimitiveElement(R, F) : SIG == CODE where
R : Join(IntegralDomain, OrderedSet, CharacteristicZero)
F : FunctionSpace R
SY ==> Symbol
P ==> Polynomial F
K ==> Kernel F
UP ==> SparseUnivariatePolynomial F
REC ==> Record(primelt:F, poly:List UP, prim:UP)
SIG ==> with
primitiveElement : List F -> Record(primelt:F, poly:List UP, prim:UP)
++ primitiveElement([a1,...,an]) returns \spad{[a, [q1,...,qn], q]}
++ such that then \spad{k(a1,...,an) = k(a)},
++ \spad{ai = qi(a)}, and \spad{q(a) = 0}.
++ This operation uses the technique of
++ \spadglossSee{groebner bases}{Groebner basis}.
if F has AlgebraicallyClosedField then
primitiveElement : (F,F)->Record(primelt:F,pol1:UP,pol2:UP,prim:UP)
++ primitiveElement(a1, a2) returns \spad{[a, q1, q2, q]}
++ such that \spad{k(a1, a2) = k(a)},
++ \spad{ai = qi(a)}, and \spad{q(a) = 0}.
++ The minimal polynomial for a2 may involve a1, but the
++ minimal polynomial for a1 may not involve a2;
++ This operations uses \spadfun{resultant}.
CODE ==> add
import PrimitiveElement(F)
import AlgebraicManipulations(R, F)
import PolynomialCategoryLifting(IndexedExponents K,
K, R, SparseMultivariatePolynomial(R, K), P)
F2P: (F, List SY) -> P
K2P: (K, List SY) -> P
F2P(f, l) ==
inv(denom(f)::F)*map((k1:K):P+->K2P(k1,l),(r1:R):P+->r1::F::P, numer f)
K2P(k, l) ==
((v := symbolIfCan k) case SY) and member?(v::SY, l) => v::SY::P
k::F::P
primitiveElement l ==
u := string(uu := new()$SY)
vars := [concat(u, string i)::SY for i in 1..#l]
vv := [kernel(v)$K :: F for v in vars]
kers := [retract(a)@K for a in l]
pols := [F2P(subst(ratDenom((minPoly k) v, kers), kers, vv), vars)
for k in kers for v in vv]
rec := primitiveElement(pols, vars, uu)
[+/[c * a for c in rec.coef for a in l], rec.poly, rec.prim]
if F has AlgebraicallyClosedField then
import PolynomialCategoryQuotientFunctions(IndexedExponents K,
K, R, SparseMultivariatePolynomial(R, K), F)
F2UP: (UP, K, UP) -> UP
getpoly: (UP, F) -> UP
F2UP(p, k, q) ==
ans:UP := 0
while not zero? p repeat
f := univariate(leadingCoefficient p, k)
ans := ans + ((numer f) q)
* monomial(inv(retract(denom f)@F), degree p)
p := reductum p
ans
primitiveElement(a1, a2) ==
a := (aa := new()$SY)::F
b := (bb := new()$SY)::F
l := [aa, bb]$List(SY)
p1 := minPoly(k1 := retract(a1)@K)
p2 := map((z1:F):F+->subst(ratDenom(z1, [k1]), [k1], [a]),
minPoly(retract(a2)@K))
rec := primitiveElement(F2P(p1 a, l), aa, F2P(p2 b, l), bb)
w := rec.coef1 * a1 + rec.coef2 * a2
g := rootOf(rec.prim)
zero?(rec.coef1) =>
c2g := inv(rec.coef2 :: F) * g
r := gcd(p1, univariate(p2 c2g, retract(a)@K, p1))
q := getpoly(r, g)
[w, q, rec.coef2 * monomial(1, 1)$UP, rec.prim]
ic1 := inv(rec.coef1 :: F)
gg := (ic1 * g)::UP - monomial(rec.coef2 * ic1, 1)$UP
kg := retract(g)@K
r := gcd(p1 gg, F2UP(p2, retract(a)@K, gg))
q := getpoly(r, g)
[w, monomial(ic1, 1)$UP - rec.coef2 * ic1 * q, q, rec.prim]
getpoly(r, g) ==
(degree r = 1) =>
k := retract(g)@K
univariate(-coefficient(r,0)/leadingCoefficient r,k,minPoly k)
error "GCD not of degree 1"
|