This file is indexed.

/usr/share/axiom-20170501/src/algebra/CHVAR.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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
)abbrev package CHVAR ChangeOfVariable
++ Author: Manuel Bronstein
++ Date Created: 1988
++ Date Last Updated: 22 Feb 1990
++ Description:
++ Tools to send a point to infinity on an algebraic curve.

ChangeOfVariable(F, UP, UPUP) : SIG == CODE where
  F : UniqueFactorizationDomain
  UP : UnivariatePolynomialCategory F
  UPUP : UnivariatePolynomialCategory Fraction UP

  N  ==> NonNegativeInteger
  Z  ==> Integer
  Q  ==> Fraction Z
  RF ==> Fraction UP

  SIG ==> with

    mkIntegral : UPUP -> Record(coef:RF, poly:UPUP)
      ++ mkIntegral(p(x,y)) returns \spad{[c(x), q(x,z)]} such that
      ++ \spad{z = c * y} is integral.
      ++ The algebraic relation between x and y is \spad{p(x, y) = 0}.
      ++ The algebraic relation between x and z is \spad{q(x, z) = 0}.

    radPoly : UPUP -> Union(Record(radicand:RF, deg:N), "failed")
      ++ radPoly(p(x, y)) returns \spad{[c(x), n]} if p is of the form
      ++ \spad{y**n - c(x)}, "failed" otherwise.

    rootPoly : (RF, N) -> Record(exponent: N, coef:RF, radicand:UP)
      ++ rootPoly(g, n) returns \spad{[m, c, P]} such that
      ++ \spad{c * g ** (1/n) = P ** (1/m)}
      ++ thus if \spad{y**n = g}, then \spad{z**m = P}
      ++ where \spad{z = c * y}.

    goodPoint : (UPUP,UPUP) -> F
      ++ goodPoint(p, q) returns an integer a such that a is neither
      ++ a pole of \spad{p(x,y)} nor a branch point of \spad{q(x,y) = 0}.

    eval : (UPUP, RF, RF) -> UPUP
      ++ eval(p(x,y), f(x), g(x)) returns \spad{p(f(x), y * g(x))}.

    chvar : (UPUP,UPUP) -> Record(func:UPUP,poly:UPUP,c1:RF,c2:RF,deg:N)
      ++ chvar(f(x,y), p(x,y)) returns
      ++ \spad{[g(z,t), q(z,t), c1(z), c2(z), n]}
      ++ such that under the change of variable
      ++ \spad{x = c1(z)}, \spad{y = t * c2(z)},
      ++ one gets \spad{f(x,y) = g(z,t)}.
      ++ The algebraic relation between x and y is \spad{p(x, y) = 0}.
      ++ The algebraic relation between z and t is \spad{q(z, t) = 0}.

  CODE ==> add

    import UnivariatePolynomialCommonDenominator(UP, RF, UPUP)

    algPoly     : UPUP           -> Record(coef:RF, poly:UPUP)
    RPrim       : (UP, UP, UPUP) -> Record(coef:RF, poly:UPUP)
    good?       : (F, UP, UP)    -> Boolean
    infIntegral?: (UPUP, UPUP)   -> Boolean

    eval(p, x, y)  == map(s +-> s(x), p)  monomial(y, 1)

    good?(a, p, q) == p(a) ^= 0 and q(a) ^= 0

    algPoly p ==
      ground?(a:= retract(leadingCoefficient(q:=clearDenominator p))@UP)
        => RPrim(1, a, q)
      c := d := squareFreePart a
      q := clearDenominator q monomial(inv(d::RF), 1)
      while not ground?(a := retract(leadingCoefficient q)@UP) repeat
        c := c * (d := gcd(a, d))
        q := clearDenominator q monomial(inv(d::RF), 1)
      RPrim(c, a, q)

    RPrim(c, a, q) ==
      (a = 1) => [c::RF, q]
      [(a * c)::RF, clearDenominator q monomial(inv(a::RF), 1)]

    -- always makes the algebraic integral, but does not send a point 
    -- to infinity
    -- if the integrand does not have a pole there (in the case of an nth-root)
    chvar(f, modulus) ==
      r1 := mkIntegral modulus
      f1 := f monomial(r1inv := inv(r1.coef), 1)
      infIntegral?(f1, r1.poly) =>
        [f1, r1.poly, monomial(1,1)$UP :: RF,r1inv,degree(retract(r1.coef)@UP)]
      x  := (a:= goodPoint(f1,r1.poly))::UP::RF + inv(monomial(1,1)::RF)
      r2c:= retract((r2 := mkIntegral map(s+->s(x), r1.poly)).coef)@UP
      t  := inv((monomial(1, 1)$UP - a::UP)::RF)
      [- inv(monomial(1, 2)$UP :: RF) * eval(f1, x, inv(r2.coef)),
                                r2.poly, t, r1.coef * r2c t, degree r2c]

    -- returns true if y is an n-th root, 
    -- and it can be guaranteed that p(x,y)dx
    -- is integral at infinity
    -- expects y to be integral.
    infIntegral?(p, modulus) ==
      (r := radPoly modulus) case "failed" => false
      ninv := inv(r.deg::Q)
      degy:Q := degree(retract(r.radicand)@UP) * ninv
      degp:Q := 0
      while p ^= 0 repeat
        c := leadingCoefficient p
        degp := max(degp,
           (2 + degree(numer c)::Z - degree(denom c)::Z)::Q + degree(p) * degy)
        p := reductum p
      degp <= ninv

    mkIntegral p ==
      (r := radPoly p) case "failed" => algPoly p
      rp := rootPoly(r.radicand, r.deg)
      [rp.coef, monomial(1, rp.exponent)$UPUP - rp.radicand::RF::UPUP]

    goodPoint(p, modulus) ==
      q :=
        (r := radPoly modulus) case "failed" =>
                   retract(resultant(modulus, differentiate modulus))@UP
        retract(r.radicand)@UP
      d := commonDenominator p
      for i in 0.. repeat
        good?(a := i::F, q, d) => return a
        good?(-a, q, d)        => return -a

    radPoly p ==
      (r := retractIfCan(reductum p)@Union(RF, "failed")) case "failed"
        => "failed"
      [- (r::RF), degree p]

    -- we have y**m = g(x) = n(x)/d(x), so if we can write
    -- (n(x) * d(x)**(m-1)) ** (1/m)  =  c(x) * P(x) ** (1/n)
    -- then z**q = P(x) where z = (d(x) / c(x)) * y
    rootPoly(g, m) ==
      zero? g => error "Should not happen"
      pr := nthRoot(squareFree((numer g) * (d := denom g) ** (m-1)::N),
                                                m)$FactoredFunctions(UP)
      [pr.exponent, d / pr.coef, */(pr.radicand)]