This file is indexed.

/usr/share/axiom-20170501/src/algebra/PR.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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
)abbrev domain PR PolynomialRing
++ Author: Dave Barton, James Davenport, Barry Trager
++ Date Created:
++ Date Last Updated: 14.08.2000. Improved exponentiation [MMM/TTT]
++ Description:
++ This domain represents generalized polynomials with coefficients
++ (from a not necessarily commutative ring), and terms
++ indexed by their exponents (from an arbitrary ordered abelian monoid).
++ This type is used, for example,
++ by the \spadtype{DistributedMultivariatePolynomial} domain where
++ the exponent domain is a direct product of non negative integers.

PolynomialRing(R,E) : SIG == CODE where
  R : Ring
  E : OrderedAbelianMonoid

  SIG ==> FiniteAbelianMonoidRing(R,E) with
    --assertions

     if R has IntegralDomain and E has CancellationAbelianMonoid then

        fmecg : (%,E,R,%) -> %
          ++ fmecg(p1,e,r,p2) finds x : p1 - r * x**e * p2

     if R has canonicalUnitNormal then canonicalUnitNormal
        ++ canonicalUnitNormal guarantees that the function
        ++ unitCanonical returns the same representative for all
        ++ associates of any particular element.
       
  CODE ==> FreeModule(R,E) add

    --representations
       Term:=  Record(k:E,c:R)
       Rep:=  List Term

    --declarations
       x,y,p,p1,p2: %
       n: Integer
       nn: NonNegativeInteger
       np: PositiveInteger
       e: E
       r: R

    --local operations

       1  == [[0$E,1$R]]

       characteristic  == characteristic$R

       numberOfMonomials x  == (# x)$Rep

       degree p == if null p then 0 else p.first.k

       minimumDegree p == if null p then 0 else (last p).k

       leadingCoefficient p == if null p then 0$R else p.first.c

       leadingMonomial p == if null p then 0 else [p.first]

       reductum p == if null p then p else p.rest

       retractIfCan(p:%):Union(R,"failed") ==
         null p => 0$R
         not null p.rest => "failed"
         zero?(p.first.k) => p.first.c
         "failed" 

       coefficient(p,e)  ==
          for tm in p repeat
            tm.k=e => return tm.c
            tm.k < e => return 0$R
          0$R

       recip(p) ==
           null p => "failed"
           p.first.k > 0$E => "failed"
           (u:=recip(p.first.c)) case "failed" => "failed"
           (u::R)::%

       coerce(r) == if zero? r then 0$% else [[0$E,r]]

       coerce(n) == (n::R)::%

       ground?(p): Boolean == empty? p or (empty? rest p and zero? degree p)

       qsetrest!: (Rep, Rep) -> Rep
       qsetrest!(l: Rep, e: Rep): Rep == RPLACD(l, e)$Lisp

       times!: (R,    %) -> %
       times:  (R, E, %) -> %

       entireRing? := R has EntireRing

       times!(r: R, x: %): % == 
         res, endcell, newend, xx: Rep
         if entireRing? then 
                for tx in x repeat tx.c := r*tx.c
         else 
                xx := x
                res := empty()
                while not empty? xx repeat 
                        tx := first xx
                        tx.c := r * tx.c
                        if zero? tx.c then 
                                xx := rest xx
                        else 
                                newend := xx
                                xx := rest xx
                                if empty? res then 
                                        res := newend
                                        endcell := res
                                else 
                                        qsetrest!(endcell, newend)
                                        endcell := newend
                res;

        --- term * polynomial 
       termTimes: (R, E, Term) -> Term
       termTimes(r: R, e: E, tx:Term): Term == [e+tx.k, r*tx.c]

       times(tco: R, tex: E, rx: %): % == 
        if entireRing? then 
            map(x1+->termTimes(tco, tex, x1), rx::Rep)
        else
            [[tex + tx.k, r] for tx in rx::Rep | not zero? (r := tco * tx.c)]



       -- local addm!
       addm!: (Rep, R, E, Rep) -> Rep
        -- p1 + coef*x^E * p2
        -- `spare' (commented out) is for storage efficiency (not so good for
        -- performance though.

       addm!(p1:Rep, coef:R, exp: E, p2:Rep): Rep == 
                --local res, newend, last: Rep
                res, newcell, endcell: Rep
                spare: List Rep
                res     := empty()
                endcell := empty()
                while not empty? p1 and not empty? p2 repeat 
                        tx := first p1
                        ty := first p2
                        exy := exp + ty.k
                        newcell := empty();
                        if tx.k = exy then 
                                newcoef := tx.c + coef * ty.c
                                if not zero? newcoef then
                                        tx.c    := newcoef
                                        newcell := p1
                                p1 := rest p1
                                p2 := rest p2
                        else if tx.k > exy then 
                                newcell := p1
                                p1      := rest p1
                        else 
                                newcoef := coef * ty.c
                                if not entireRing? and zero? newcoef then
                                        newcell := empty()
                                else
                                        ttt := [exy, newcoef]
                                        newcell := cons(ttt, empty())
                                p2 := rest p2
                        if not empty? newcell then
                                if empty? res then
                                        res := newcell
                                        endcell := res
                                else
                                        qsetrest!(endcell, newcell)
                                        endcell := newcell
                if not empty? p1 then  -- then end is const * p1
                        newcell := p1
                else  -- then end is (coef, exp) * p2
                        newcell := times(coef, exp, p2)
                empty? res => newcell
                qsetrest!(endcell, newcell)
                res

       pomopo! (p1, r, e, p2) ==  addm!(p1, r, e, p2)

       p1 * p2 == 
                xx := p1::Rep
                empty? xx => p1
                yy := p2::Rep
                empty? yy => p2
                zero? first(xx).k => first(xx).c * p2
                zero? first(yy).k => p1 * first(yy).c
                --if #xx > #yy then 
                --        (xx, yy) := (yy, xx)
                --        (p1, p2) := (p2, p1)
                xx := reverse xx
                res : Rep := empty()
                for tx in xx repeat res:=addm!(res,tx.c,tx.k,yy)
                res

       if R has CommutativeRing  then

         p ** np == p ** (np pretend NonNegativeInteger)

         p ^ np  == p ** (np pretend NonNegativeInteger)

         p ^ nn  == p ** nn
            

         p ** nn  ==
            null p => 0
            zero? nn => 1
            (nn = 1) => p
            empty? p.rest =>
              zero?(cc:=p.first.c ** nn) => 0
              [[nn * p.first.k, cc]]
            binomThmExpt([p.first], p.rest, nn)

       if R has Field then

         unitNormal(p) ==
            null p or (lcf:R:=p.first.c) = 1 => [1,p,1]
            a := inv lcf
            [lcf::%, [[p.first.k,1],:(a * p.rest)], a::%]

         unitCanonical(p) ==
            null p or (lcf:R:=p.first.c) = 1 => p
            a := inv lcf
            [[p.first.k,1],:(a * p.rest)]

       else if R has IntegralDomain then

         unitNormal(p) ==
            null p or p.first.c = 1 => [1,p,1]
            (u,cf,a):=unitNormal(p.first.c)
            [u::%, [[p.first.k,cf],:(a * p.rest)], a::%]

         unitCanonical(p) ==
            null p or p.first.c = 1 => p
            (u,cf,a):=unitNormal(p.first.c)
            [[p.first.k,cf],:(a * p.rest)]

       if R has IntegralDomain then

         associates?(p1,p2) ==
            null p1 => null p2
            null p2 => false
            p1.first.k = p2.first.k and
              associates?(p1.first.c,p2.first.c) and
               ((p2.first.c exquo p1.first.c)::R * p1.rest = p2.rest)

         p exquo r  ==
           [(if (a:= tm.c exquo r) case "failed"
               then return "failed" else [tm.k,a])
                  for tm in p] :: Union(%,"failed")

         if E has CancellationAbelianMonoid then

           fmecg(p1:%,e:E,r:R,p2:%):% ==       -- p1 - r * X**e * p2
              rout:%:= []
              r:= - r
              for tm in p2 repeat
                 e2:= e + tm.k
                 c2:= r * tm.c
                 c2 = 0 => "next term"
                 while not null p1 and p1.first.k > e2 repeat
                   (rout:=[p1.first,:rout]; p1:=p1.rest)  --use PUSH and POP?
                 null p1 or p1.first.k < e2 => rout:=[[e2,c2],:rout]
                 if (u:=p1.first.c + c2) ^= 0 then rout:=[[e2, u],:rout]
                 p1:=p1.rest
              NRECONC(rout,p1)$Lisp

           if R has approximate then

             p1 exquo p2  ==
               null p2 => error "Division by 0"
               p2 = 1 => p1
               p1=p2 => 1
             --(p1.lastElt.c exquo p2.lastElt.c) case "failed" => "failed"
               rout:= []@List(Term)
               while not null p1 repeat
                  (a:= p1.first.c exquo p2.first.c)
                  a case "failed" => return "failed"
                  ee:= subtractIfCan(p1.first.k, p2.first.k)
                  ee case "failed" => return "failed"
                  p1:= fmecg(p1.rest, ee, a, p2.rest)
                  rout:= [[ee,a], :rout]
               null p1 => reverse(rout)::%    -- nreverse?
               "failed"

           else -- R not approximate

             p1 exquo p2  ==
               null p2 => error "Division by 0"
               p2 = 1 => p1
               rout:= []@List(Term)
               while not null p1 repeat
                  (a:= p1.first.c exquo p2.first.c)
                  a case "failed" => return "failed"
                  ee:= subtractIfCan(p1.first.k, p2.first.k)
                  ee case "failed" => return "failed"
                  p1:= fmecg(p1.rest, ee, a, p2.rest)
                  rout:= [[ee,a], :rout]
               null p1 => reverse(rout)::%    -- nreverse?
               "failed"

       if R has Field then

          x/r == inv(r)*x