1
1
export GeneralizedEuclideanAlgorithm
2
2
3
+ _copy (p, :: MA.IsMutable ) = p
4
+ _copy (p, :: MA.IsNotMutable ) = copy (p)
5
+
3
6
"""
4
7
abstract type AbstractUnivariateGCDAlgorithm end
5
8
@@ -51,8 +54,12 @@ _coefficient_gcd(α, β::AbstractFloat) = one(Base.promote_typeof(α, β))
51
54
_coefficient_gcd (α:: AbstractFloat , β:: AbstractFloat ) = one (Base. promote_typeof (α, β))
52
55
53
56
Base. lcm (p:: APL , q:: APL , algo:: AbstractUnivariateGCDAlgorithm = GeneralizedEuclideanAlgorithm ()) = p * div (q, gcd (p, q, algo))
54
- Base. gcd (α, p:: APL , algo:: AbstractUnivariateGCDAlgorithm = GeneralizedEuclideanAlgorithm ()) = _coefficient_gcd (α, content (p, algo))
55
- Base. gcd (p:: APL , α, algo:: AbstractUnivariateGCDAlgorithm = GeneralizedEuclideanAlgorithm ()) = _coefficient_gcd (content (p, algo), α)
57
+ function Base. gcd (α, p:: APL , algo:: AbstractUnivariateGCDAlgorithm = GeneralizedEuclideanAlgorithm (), mα:: MA.MutableTrait = MA. IsNotMutable (), mp:: MA.MutableTrait = MA. IsNotMutable ())
58
+ return _coefficient_gcd (α, content (p, algo, mp))
59
+ end
60
+ function Base. gcd (p:: APL , α, algo:: AbstractUnivariateGCDAlgorithm = GeneralizedEuclideanAlgorithm (), mp:: MA.MutableTrait = MA. IsNotMutable (), mα:: MA.MutableTrait = MA. IsNotMutable ())
61
+ return _coefficient_gcd (content (p, algo, mp), α)
62
+ end
56
63
57
64
# function MA.promote_operation(::typeof(gcd), P::Type{<:Number}, Q::Type{<:Number})
58
65
# return typeof(gcd(one(P), one(Q)))
@@ -106,14 +113,14 @@ This is the [`GeneralizedEuclideanAlgorithm`](@ref).
106
113
*Art of computer programming, volume 2: Seminumerical algorithms.*
107
114
Addison-Wesley Professional. Third edition.
108
115
"""
109
- function Base. gcd (p1:: APL{T} , p2:: APL{S} , algo:: AbstractUnivariateGCDAlgorithm = GeneralizedEuclideanAlgorithm ()) where {T, S}
116
+ function Base. gcd (p1:: APL{T} , p2:: APL{S} , algo:: AbstractUnivariateGCDAlgorithm = GeneralizedEuclideanAlgorithm (), m1 :: MA.MutableTrait = MA . IsNotMutable (), m2 :: MA.MutableTrait = MA . IsNotMutable () ) where {T, S}
110
117
# If one of these is zero, `shift` should be infinite
111
118
# for this method to work so we exclude these cases.
112
119
if isapproxzero (p1)
113
- return convert (MA. promote_operation (gcd, typeof (p1), typeof (p2)), p2 )
120
+ return convert (MA. promote_operation (gcd, typeof (p1), typeof (p2)), _copy (p2, m2) )
114
121
end
115
122
if isapproxzero (p2)
116
- return convert (MA. promote_operation (gcd, typeof (p1), typeof (p2)), p1 )
123
+ return convert (MA. promote_operation (gcd, typeof (p1), typeof (p2)), _copy (p1, m1) )
117
124
end
118
125
shift1, defl1 = deflation (p1)
119
126
shift2, defl2 = deflation (p2)
@@ -125,11 +132,11 @@ function Base.gcd(p1::APL{T}, p2::APL{S}, algo::AbstractUnivariateGCDAlgorithm=G
125
132
# Then, we subsitute `y[i] = x[i]^defl[i]`.
126
133
q1 = deflate (p1, shift1, defl)
127
134
q2 = deflate (p2, shift2, defl)
128
- g = deflated_gcd (q1, q2, algo)
135
+ g = deflated_gcd (q1, q2, algo, m1, m2 )
129
136
return inflate (g, shift, defl):: MA.promote_operation (gcd, typeof (p1), typeof (p2))
130
137
end
131
138
132
- function Base. gcd (t1:: AbstractTermLike{T} , t2:: AbstractTermLike{S} , algo:: AbstractUnivariateGCDAlgorithm = GeneralizedEuclideanAlgorithm ()) where {T, S}
139
+ function Base. gcd (t1:: AbstractTermLike{T} , t2:: AbstractTermLike{S} , algo:: AbstractUnivariateGCDAlgorithm = GeneralizedEuclideanAlgorithm (), m1 :: MA.MutableTrait = MA . IsNotMutable (), m2 :: MA.MutableTrait = MA . IsNotMutable () ) where {T, S}
133
140
return term (_coefficient_gcd (coefficient (t1), coefficient (t2)), gcd (monomial (t1), monomial (t2)))
134
141
end
135
142
@@ -211,36 +218,36 @@ function MA.operate(op::Union{typeof(deflate), typeof(inflate)}, p::AbstractPoly
211
218
end )
212
219
end
213
220
214
- function deflated_gcd (p1:: APL{T} , p2:: APL{S} , algo) where {T, S}
221
+ function deflated_gcd (p1:: APL{T} , p2:: APL{S} , algo, m1 :: MA.MutableTrait , m2 :: MA.MutableTrait ) where {T, S}
215
222
i1, i2, num_common = _extracted_variable (p1, p2)
216
223
if iszero (i1)
217
224
if iszero (i2)
218
- return univariate_gcd (p1, p2, algo)
225
+ return univariate_gcd (p1, p2, algo, m1, m2 )
219
226
else
220
227
if isapproxzero (p1)
221
- return convert (MA. promote_operation (gcd, typeof (p1), typeof (p2)), p2 )
228
+ return convert (MA. promote_operation (gcd, typeof (p1), typeof (p2)), _copy (p2, m2) )
222
229
end
223
230
v2 = variables (p2)[i2]
224
- q2 = isolate_variable (p2, v2)
225
- g = content (q2, algo)
226
- return gcd (p1, g, algo)
231
+ q2 = isolate_variable (p2, v2, m2 )
232
+ g = content (q2, algo, MA . IsMutable () )
233
+ return gcd (p1, g, algo, m1, MA . IsMutable () )
227
234
end
228
235
else
229
236
if iszero (i2)
230
237
if isapproxzero (p2)
231
- return convert (MA. promote_operation (gcd, typeof (p1), typeof (p2)), p1 )
238
+ return convert (MA. promote_operation (gcd, typeof (p1), typeof (p2)), _copy (p1, m1) )
232
239
end
233
240
v1 = variables (p1)[i1]
234
- q1 = isolate_variable (p1, v1)
235
- g = content (q1, algo)
236
- return gcd (g, p2, algo)
241
+ q1 = isolate_variable (p1, v1, m1 )
242
+ g = content (q1, algo, MA . IsMutable () )
243
+ return gcd (g, p2, algo, MA . IsMutable (), m2 )
237
244
else
238
245
if num_common > 1
239
246
v1 = variables (p1)[i1]
240
247
@assert v1 == variables (p2)[i2]
241
- return multivariate_gcd (p1, p2, v1, algo)
248
+ return multivariate_gcd (p1, p2, v1, algo, m1, m2 )
242
249
else
243
- return univariate_gcd (p1, p2, algo)
250
+ return univariate_gcd (p1, p2, algo, m1, m2 )
244
251
end
245
252
end
246
253
end
@@ -332,35 +339,53 @@ function _extracted_variable(p1, p2)
332
339
return best_var1, best_var2, num_common
333
340
end
334
341
335
- function multivariate_gcd (p1:: APL , p2:: APL , var, algo)
336
- q = univariate_gcd (isolate_variable (p1, var), isolate_variable (p2, var), algo)
342
+ function multivariate_gcd (p1:: APL , p2:: APL , var, algo, m1 :: MA.MutableTrait , m2 :: MA.MutableTrait )
343
+ q = univariate_gcd (isolate_variable (p1, var, m1 ), isolate_variable (p2, var, m2 ), algo, MA . IsMutable (), MA . IsMutable () )
337
344
return sum (coefficient (t) * monomial (t) for t in terms (q)):: MA.promote_operation (gcd, typeof (p1), typeof (p2))
338
345
end
339
346
340
- function isolate_variable (poly:: APL , var:: AbstractVariable )
341
- T = typeof (substitute (Subs (), zeroterm (poly), (var,) => (1 ,)))
342
- dict = Dict {Int,Vector{T}} ()
343
- for t in terms (poly)
344
- d = degree (t, var)
345
- dict_ts = get (dict, d, nothing )
346
- ts = dict_ts === nothing ? T[] : dict_ts
347
- push! (ts, subs (t, (var,) => (1 ,)))
348
- if dict_ts === nothing
349
- dict[d] = ts
347
+ _vector (t:: AbstractVector ) = collect (t)
348
+ _vector (t:: Vector ) = t
349
+
350
+ """
351
+ isolate_variable(poly::APL, var::AbstractVariable, mutability::MA.MutableTrait)
352
+
353
+ Returns a polynomial with variable `var`. The other variables of `poly` are moved as coefficients.
354
+
355
+ The output can be mutated without affecting `poly` if `mutability` is
356
+ `MA.IsNotMutable`.
357
+ """
358
+ function isolate_variable (poly:: APL , var:: AbstractVariable , mutability:: MA.MutableTrait )
359
+ old_terms = sort! (_vector (terms (_copy (poly, mutability))), by = Base. Fix2 (degree, var), rev= true )
360
+ T = termtype (var, typeof (substitute (Subs (), zero (poly), (var,) => (1 ,))))
361
+ new_terms = T[]
362
+ i = firstindex (old_terms)
363
+ while i <= lastindex (old_terms)
364
+ j = i + 1
365
+ d = degree (old_terms[i], var)
366
+ while j <= lastindex (old_terms)
367
+ if degree (old_terms[j], var) != d
368
+ break
369
+ end
370
+ j += 1
350
371
end
372
+ coef = _polynomial ([subs (old_terms[k], (var,) => (1 ,)) for k in i: (j - 1 )], SortedUniqState (), mutability)
373
+ push! (new_terms, term (coef, var^ d))
374
+ i = j
351
375
end
352
- return polynomial ([
353
- term (polynomial (ts), var^ d) for (d, ts) in dict
354
- ])
376
+ return polynomial! (new_terms, SortedUniqState ())
355
377
end
356
378
379
+ _polynomial (ts, state, :: MA.IsNotMutable ) = polynomial (ts, state)
380
+ _polynomial (ts, state, :: MA.IsMutable ) = polynomial! (ts, state)
381
+
357
382
"""
358
- primitive_univariate_gcd(p::APL, q::APL, algo::AbstractUnivariateGCDAlgorithm)
383
+ primitive_univariate_gcd! (p::APL, q::APL, algo::AbstractUnivariateGCDAlgorithm)
359
384
360
385
Returns the `gcd` of primitive polynomials `p` and `q` using algorithm `algo`
361
386
which is a subtype of [`AbstractUnivariateGCDAlgorithm`](@ref).
362
387
"""
363
- function primitive_univariate_gcd end
388
+ function primitive_univariate_gcd! end
364
389
365
390
function not_divided_error (u, v)
366
391
error (
376
401
377
402
# If `p` and `q` do not have the same time then the local variables `p` and `q`
378
403
# won't be type stable.
379
- function primitive_univariate_gcd (p:: APL , q:: APL , algo:: GeneralizedEuclideanAlgorithm )
404
+ function primitive_univariate_gcd! (p:: APL , q:: APL , algo:: GeneralizedEuclideanAlgorithm )
380
405
if maxdegree (p) < maxdegree (q)
381
- return primitive_univariate_gcd (q, p, algo)
406
+ return primitive_univariate_gcd! (q, p, algo)
382
407
end
383
408
R = MA. promote_operation (gcd, typeof (p), typeof (q))
384
409
u = convert (R, p)
@@ -396,7 +421,7 @@ function primitive_univariate_gcd(p::APL, q::APL, algo::GeneralizedEuclideanAlgo
396
421
not_divided_error (u, v)
397
422
end
398
423
if ! algo. primitive_rem
399
- r = primitive_part (r, algo):: R
424
+ r = primitive_part (r, algo, MA . IsMutable () ):: R
400
425
end
401
426
u, v = v, r:: R
402
427
end
@@ -438,7 +463,7 @@ function primitive_univariate_gcdx(u0::APL, v0::APL, algo::GeneralizedEuclideanA
438
463
end
439
464
440
465
441
- function primitive_univariate_gcd (p:: APL , q:: APL , :: SubresultantAlgorithm )
466
+ function primitive_univariate_gcd! (p:: APL , q:: APL , :: SubresultantAlgorithm )
442
467
error (" Not implemented yet" )
443
468
end
444
469
@@ -457,118 +482,121 @@ If the coefficients are not `AbstractFloat`, this
457
482
[`primitive_part`](@ref) using [`primitive_part_content`](@ref); see
458
483
[Knu14, Algorithm E: E1, p. 426] or [Knu14, Algorithm C: C1, p. 428].
459
484
2. Computes the [`gcd`](@ref) of the contents and primitive parts, using
460
- [`primitive_univariate_gcd`](@ref) for primitive parts.
485
+ [`primitive_univariate_gcd! `](@ref) for primitive parts.
461
486
3. Return the product of these two `gcd`; see
462
487
[Knu14, Algorithm E: E4, p. 427] or [Knu14, Algorithm C: C4, p. 429].
463
488
464
489
[Knu14] Knuth, D.E., 2014.
465
490
*Art of computer programming, volume 2: Seminumerical algorithms.*
466
491
Addison-Wesley Professional. Third edition.
467
492
"""
468
- function univariate_gcd (p1:: APL{S} , p2:: APL{T} , algo:: AbstractUnivariateGCDAlgorithm ) where {S,T}
469
- return univariate_gcd (_field_absorb (algebraic_structure (S), algebraic_structure (T)), p1, p2, algo)
470
- end
471
- function univariate_gcd (:: UFD , p1:: APL , p2:: APL , algo:: AbstractUnivariateGCDAlgorithm )
472
- f1, g1 = primitive_part_content (p1, algo)
473
- f2, g2 = primitive_part_content (p2, algo)
474
- pp = primitive_univariate_gcd (f1, f2, algo)
475
- gg = _gcd (g1, g2, algo)# ::MA.promote_operation(gcd, typeof(g1), typeof(g2))
493
+ function univariate_gcd (p1:: APL{S} , p2:: APL{T} , algo:: AbstractUnivariateGCDAlgorithm , m1 :: MA.MutableTrait , m2 :: MA.MutableTrait ) where {S,T}
494
+ return univariate_gcd (_field_absorb (algebraic_structure (S), algebraic_structure (T)), p1, p2, algo, m1, m2 )
495
+ end
496
+ function univariate_gcd (:: UFD , p1:: APL , p2:: APL , algo:: AbstractUnivariateGCDAlgorithm , m1 :: MA.MutableTrait , m2 :: MA.MutableTrait )
497
+ f1, g1 = primitive_part_content (p1, algo, m1 )
498
+ f2, g2 = primitive_part_content (p2, algo, m2 )
499
+ pp = primitive_univariate_gcd! (f1, f2, algo)
500
+ gg = _gcd (g1, g2, algo, MA . IsMutable (), MA . IsMutable () )# ::MA.promote_operation(gcd, typeof(g1), typeof(g2))
476
501
# Multiply each coefficient by the gcd of the contents.
477
- return mapcoefficientsnz (Base. Fix1 (* , gg), pp)
502
+ return mapcoefficients! (Base. Fix1 (* , gg), pp, nonzero = true )
478
503
end
479
504
480
- function univariate_gcd (:: Field , p1:: APL , p2:: APL , algo:: AbstractUnivariateGCDAlgorithm )
481
- return primitive_univariate_gcd (p1, p2, algo)
505
+ function univariate_gcd (:: Field , p1:: APL , p2:: APL , algo:: AbstractUnivariateGCDAlgorithm , m1 :: MA.MutableTrait , m2 :: MA.MutableTrait )
506
+ return primitive_univariate_gcd! (p1, p2, algo)
482
507
end
483
508
484
509
function univariate_gcdx (p1:: APL{S} , p2:: APL{T} , algo:: AbstractUnivariateGCDAlgorithm ) where {S,T}
485
510
return univariate_gcdx (_field_absorb (algebraic_structure (S), algebraic_structure (T)), p1, p2, algo)
486
511
end
487
512
function univariate_gcdx (:: UFD , p1:: APL , p2:: APL , algo:: AbstractUnivariateGCDAlgorithm )
488
- f1, g1 = primitive_part_content (p1, algo)
489
- f2, g2 = primitive_part_content (p2, algo)
513
+ f1, g1 = primitive_part_content (p1, algo, MA . IsNotMutable () )
514
+ f2, g2 = primitive_part_content (p2, algo, MA . IsNotMutable () )
490
515
a, b, pp = primitive_univariate_gcdx (f1, f2, algo)
491
- gg = _gcd (g1, g2, algo)# ::MA.promote_operation(gcd, typeof(g1), typeof(g2))
516
+ gg = _gcd (g1, g2, algo, MA . IsMutable (), MA . IsMutable () )# ::MA.promote_operation(gcd, typeof(g1), typeof(g2))
492
517
# Multiply each coefficient by the gcd of the contents.
493
- return g2 * a, g1 * b, g1 * g2 * mapcoefficientsnz (Base. Fix1 (* , gg), pp)
518
+ return g2 * a, g1 * b, g1 * g2 * mapcoefficients (Base. Fix1 (* , gg), pp, nonzero = true )
494
519
end
495
520
function univariate_gcdx (:: Field , p1:: APL , p2:: APL , algo:: AbstractUnivariateGCDAlgorithm )
496
521
return primitive_univariate_gcdx (p1, p2, algo)
497
522
end
498
523
499
- _gcd (a:: APL , b:: APL , algo) = gcd (a, b, algo)
500
- _gcd (a, b:: APL , algo) = gcd (a, b, algo)
501
- _gcd (a:: APL , b, algo) = gcd (a, b, algo)
502
- _gcd (a, b, algo) = gcd (a, b)
524
+ _gcd (a:: APL , b:: APL , algo, ma, mb ) = gcd (a, b, algo, ma, mb )
525
+ _gcd (a, b:: APL , algo, ma, mb ) = gcd (a, b, algo, ma, mb )
526
+ _gcd (a:: APL , b, algo, ma, mb ) = gcd (a, b, algo, ma, mb )
527
+ _gcd (a, b, algo, ma, mb ) = gcd (a, b)
503
528
504
- _simplifier (a:: APL , b:: APL , algo) = gcd (a, b, algo)
505
- _simplifier (a, b, algo) = _gcd (a, b, algo)
529
+ _simplifier (a:: APL , b:: APL , algo, ma, mb ) = gcd (a, b, algo, ma, mb )
530
+ _simplifier (a, b, algo, ma, mb ) = _gcd (a, b, algo, ma, mb )
506
531
# Before Julia v1.4, it is not defined.
507
532
# After Julia v1.4, it is defined as `gcd of num / lcm of den`.
508
533
# We prefer `gcd of den`, otherwise,
509
534
# `1/a0 + 1/a1 x + 1/a2 x^2 + ... + 1/an x^n`
510
535
# will be transformed into
511
536
# `a1*a2*...*an + a0*a2*...*an x + ...`
512
537
# which makes the size of the `BigInt`s grow significantly which slows things down.
513
- _simplifier (a:: Rational , b:: Rational , algo) = gcd (a. num, b. num) // gcd (a. den, b. den)
538
+ _simplifier (a:: Rational , b:: Rational , algo, ma, mb ) = gcd (a. num, b. num) // gcd (a. den, b. den)
514
539
515
540
# Largely inspired from from `YingboMa/SIMDPolynomials.jl`.
516
- function termwise_content (p:: APL )
541
+ function termwise_content (p:: APL , algo, mutability :: MA.MutableTrait )
517
542
ts = terms (p)
518
- length (ts) == 1 && return first (ts)
519
- g = gcd (ts[1 ], ts[2 ])
543
+ length (ts) == 1 && return _copy ( first (ts), mutability )
544
+ g = gcd (ts[1 ], ts[2 ], algo, mutability, mutability )
520
545
isone (g) || for i in 3 : length (ts)
521
- g = gcd (g, ts[i])
546
+ g = gcd (g, ts[i], algo, MA . IsMutable (), mutability )
522
547
isone (g) && break
523
548
end
524
549
return g
525
550
end
526
551
527
552
"""
528
- content(poly::AbstractPolynomialLike{T}, algo::AbstractUnivariateGCDAlgorithm) where {T}
553
+ content(poly::AbstractPolynomialLike{T}, algo::AbstractUnivariateGCDAlgorithm, mutability::MA.MutableTrait ) where {T}
529
554
530
555
Return the *content* of the polynomial `poly` over a unique factorization
531
556
domain `S` as defined in [Knu14, (3) p. 423].
532
557
That is, return the `gcd` of the coefficients of `poly`.
533
558
See also [`primitive_part_content`](@ref).
534
559
560
+ The output can be mutated without affecting `poly` if `mutability` is
561
+ `MA.IsNotMutable`.
562
+
535
563
[Knu14] Knuth, D.E., 2014.
536
564
*Art of computer programming, volume 2: Seminumerical algorithms.*
537
565
Addison-Wesley Professional. Third edition.
538
566
"""
539
- function content (poly:: APL{T} , algo:: AbstractUnivariateGCDAlgorithm ) where {T}
567
+ function content (poly:: APL{T} , algo:: AbstractUnivariateGCDAlgorithm , mutability :: MA.MutableTrait ) where {T}
540
568
P = MA. promote_operation (gcd, T, T)
541
- # This is tricky to infer a `content` calls `gcd` which calls `content`, etc...
542
- # To help Julia break the loop, we annotate the result here.
543
569
coefs = coefficients (poly)
544
- length (coefs) == 0 && return zero (T )
545
- length (coefs) == 1 && return first (coefs)
570
+ isempty (coefs) && return zero (P )
571
+ length (coefs) == 1 && return convert (P, _copy ( first (coefs), mutability) )
546
572
# Largely inspired from from `YingboMa/SIMDPolynomials.jl`.
547
573
if T <: APL
548
574
for i in eachindex (coefs)
549
575
if nterms (coefs[i]) == 1
550
- g = gcd (termwise_content (coefs[1 ]), termwise_content (coefs[2 ]))
576
+ g = _gcd (termwise_content (coefs[1 ], algo, mutability ), termwise_content (coefs[2 ], algo, mutability), algo, MA . IsMutable (), MA . IsMutable ( ))
551
577
isone (g) || for i in 3 : length (coefs)
552
- g = gcd (g, termwise_content (coefs[i]))
578
+ g = _gcd (g, termwise_content (coefs[i], algo, mutability), algo, MA . IsMutable (), MA . IsMutable ( ))
553
579
isone (g) && break
554
580
end
555
581
return convert (P, g)
556
582
end
557
583
end
558
584
end
559
- g = gcd (coefs[1 ], coefs[2 ]):: P
585
+ # This is tricky to infer a `content` calls `gcd` which calls `content`, etc...
586
+ # To help Julia break the loop, we annotate the result here.
587
+ g = _gcd (coefs[1 ], coefs[2 ], algo, mutability, mutability):: P
560
588
isone (g) || for i in 3 : length (coefs)
561
- g = _simplifier (g, coefs[i], algo):: P
589
+ g = _simplifier (g, coefs[i], algo, MA . IsMutable (), mutability ):: P
562
590
isone (g) && break
563
591
end
564
592
return g:: P
565
593
end
566
- function content (poly:: APL{T} , algo :: AbstractUnivariateGCDAlgorithm ) where {T<: AbstractFloat }
594
+ function content (poly:: APL{T} , :: AbstractUnivariateGCDAlgorithm , :: MA.MutableTrait ) where {T<: AbstractFloat }
567
595
return one (T)
568
596
end
569
597
570
598
"""
571
- primitive_part_content (poly::AbstractPolynomialLike{T}, algo::AbstractUnivariateGCDAlgorithm) where {T}
599
+ primitive_part (poly::AbstractPolynomialLike{T}, algo::AbstractUnivariateGCDAlgorithm) where {T}
572
600
573
601
Return the *primitive part* of the polynomial `poly` over a unique
574
602
factorization domain `S` as defined in [Knu14, (3) p. 423].
@@ -580,8 +608,8 @@ instead.
580
608
*Art of computer programming, volume 2: Seminumerical algorithms.*
581
609
Addison-Wesley Professional. Third edition.
582
610
"""
583
- primitive_part (p:: APL , algo:: AbstractUnivariateGCDAlgorithm ) = primitive_part_content (p, algo)[1 ]
584
- primitive_part (p:: APL{<:AbstractFloat} , algo :: AbstractUnivariateGCDAlgorithm ) = p
611
+ primitive_part (p:: APL , algo:: AbstractUnivariateGCDAlgorithm , mutability :: MA.MutableTrait ) = primitive_part_content (p, algo, mutability )[1 ]
612
+ primitive_part (p:: APL{<:AbstractFloat} , :: AbstractUnivariateGCDAlgorithm , :: MA.MutableTrait ) = p
585
613
586
614
"""
587
615
primitive_part_content(poly::AbstractPolynomialLike{T}, algo::AbstractUnivariateGCDAlgorithm) where {T}
@@ -596,7 +624,7 @@ computing the content first and this function avoid computing the content twice.
596
624
*Art of computer programming, volume 2: Seminumerical algorithms.*
597
625
Addison-Wesley Professional. Third edition.
598
626
"""
599
- function primitive_part_content (p, algo:: AbstractUnivariateGCDAlgorithm )
600
- g = content (p, algo)
601
- return mapcoefficientsnz (Base. Fix2 (_div, g), p), g
627
+ function primitive_part_content (p, algo:: AbstractUnivariateGCDAlgorithm , mutability :: MA.MutableTrait )
628
+ g = content (p, algo, MA . IsNotMutable () )
629
+ return mapcoefficients (Base. Fix2 (_div, g), p, mutability; nonzero = true ), g
602
630
end
0 commit comments