Skip to content

Commit f9df0ba

Browse files
authored
Improve docs for division (#299)
* Improve docs for division * Fixes
1 parent 8a31f0a commit f9df0ba

File tree

7 files changed

+98
-6
lines changed

7 files changed

+98
-6
lines changed

docs/make.jl

+6-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,12 @@ makedocs(
1616
"Substitution" => "substitution.md",
1717
"Differentiation" => "differentiation.md",
1818
"Division" => "division.md",
19-
]
19+
"Internal" => "internal.md",
20+
],
21+
22+
# The following ensures that we only include the docstrings from
23+
# this module for functions define in Base that we overwrite.
24+
modules = [MultivariatePolynomials],
2025
)
2126

2227
deploydocs(

docs/src/division.md

+30-3
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,45 @@
11
# Division
22

3-
The `gcd` and `lcm` functions of `Base` have been implemented for monomials, you have for example `gcd(x^2*y^7*z^3, x^4*y^5*z^2)` returning `x^2*y^5*z^2` and `lcm(x^2*y^7*z^3, x^4*y^5*z^2)` returning `x^4*y^7*z^3`.
4-
53
Given two polynomials, ``p`` and ``d``, there are unique ``r`` and ``q`` such that ``p = q d + r`` and the leading term of ``d`` does not divide the leading term of ``r``.
64
You can obtain ``q`` using the `div` function and ``r`` using the `rem` function.
75
The `divrem` function returns ``(q, r)``.
86

97
Given a polynomial ``p`` and divisors ``d_1, \ldots, d_n``, one can find ``r`` and ``q_1, \ldots, q_n`` such that ``p = q_1 d_1 + \cdots + q_n d_n + r`` and none of the leading terms of ``q_1, \ldots, q_n`` divide the leading term of ``r``.
108
You can obtain the vector ``[q_1, \ldots, q_n]`` using `div(p, d)` where ``d = [d_1, \ldots, d_n]`` and ``r`` using the `rem` function with the same arguments.
119
The `divrem` function returns ``(q, r)``.
12-
1310
```@docs
1411
divides
1512
div_multiple
13+
```
14+
15+
Note that the coefficients of the polynomials need to be a field for `div`,
16+
`rem` and `divrem` to work.
17+
Alternatively, [`pseudo_rem`](@ref) or [`pseudo_divrem`](@ref) can be used
18+
instead as they do not require the coefficient type to be a field.
19+
```@docs
1620
pseudo_rem
21+
pseudo_divrem
1722
rem_or_pseudo_rem
1823
```
24+
25+
## Greatest Common Divisor (GCD)
26+
27+
The Greatest Common Divisor (GCD) and Least Common Multiple (LCM) can be
28+
obtained for integers respectively with the `gcd` and `lcm` functions.
29+
The same functions can be used with monomials and polynomials:
30+
```@docs
31+
gcd
32+
lcm
33+
AbstractUnivariateGCDAlgorithm
34+
GeneralizedEuclideanAlgorithm
35+
SubresultantAlgorithm
36+
```
37+
Internal functions of the `gcd` algorithm:
38+
```@docs
39+
isolate_variable
40+
primitive_univariate_gcd!
41+
univariate_gcd
42+
content
43+
primitive_part
44+
primitive_part_content
45+
```

docs/src/index.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,6 @@ The following packages extend the interface and/or implement algorithms using th
2424

2525
## Contents
2626
```@contents
27-
Pages = ["types.md", "substitution.md", "differentiation.md", "division.md"]
27+
Pages = ["types.md", "substitution.md", "differentiation.md", "division.md", "internal.md"]
2828
Depth = 3
2929
```

docs/src/internal.md

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Internal
2+
3+
Internal utilities:
4+
```@docs
5+
pair_zip
6+
vec
7+
print_maybe_multiplication_sign
8+
LazyMap
9+
```

docs/src/substitution.md

+1
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@ However, if some variables only are replaced by `Int` then the return type shoul
1212

1313
```@docs
1414
subs
15+
substitute
1516
```

docs/src/types.md

+1
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ extdegree
9090
leading_term
9191
leading_coefficient
9292
leading_monomial
93+
deg_num_leading_terms
9394
remove_leading_term
9495
remove_monomials
9596
filter_terms

src/division.jl

+50-1
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,36 @@ function divides(t1::AbstractTermLike, t2::AbstractTermLike)
2626
end
2727
divides(t1::AbstractVariable, t2::AbstractVariable) = t1 == t2
2828

29+
"""
30+
gcd(m1::AbstractMonomialLike, m2::AbstractMonomialLike)
31+
32+
Return the largest monomial `m` such that both `divides(m, m1)`
33+
and `divides(m, m2)` are `true`.
34+
35+
```@example
36+
julia> @polyvar x y z;
37+
38+
julia> gcd(x^2*y^7*z^3, x^4*y^5*z^2)
39+
x²y⁵z²
40+
```
41+
"""
2942
function Base.gcd(m1::AbstractMonomialLike, m2::AbstractMonomialLike)
3043
return map_exponents(min, m1, m2)
3144
end
45+
46+
"""
47+
lcm(m1::AbstractMonomialLike, m2::AbstractMonomialLike)
48+
49+
Return the smallest monomial `m` such that both `divides(m1, m)`
50+
and `divides(m2, m)` are `true`.
51+
52+
```@example
53+
julia> @polyvar x y z;
54+
55+
julia> lcm(x^2*y^7*z^3, x^4*y^5*z^2)
56+
x^4*y^7*z^3
57+
```
58+
"""
3259
function Base.lcm(m1::AbstractMonomialLike, m2::AbstractMonomialLike)
3360
return map_exponents(max, m1, m2)
3461
end
@@ -152,6 +179,26 @@ function Base.rem(f::_APL, g::Union{_APL,AbstractVector{<:_APL}}; kwargs...)
152179
return divrem(f, g; kwargs...)[2]
153180
end
154181

182+
"""
183+
pseudo_divrem(f::_APL{S}, g::_APL{T}, algo) where {S,T}
184+
185+
Return the pseudo divisor and remainder of `f` modulo `g` as defined in [Knu14, Algorithm R, p. 425].
186+
187+
When the coefficient type is not a field, it is not always possible to carry a
188+
division. For instance, the division of `f = 3x + 1` by `g = 2x + 1` cannot be done over
189+
integers. On the other hand, one can write `2f = 3g - 1`.
190+
In general, the *pseudo* division of `f` by `g` is:
191+
```math
192+
l f(x) = q(x) g(x) + r(x)
193+
```
194+
where `l` is a power of the leading coefficient of `g` some constant.
195+
196+
See also [`pseudo_rem`](@ref).
197+
198+
[Knu14] Knuth, D.E., 2014.
199+
*Art of computer programming, volume 2: Seminumerical algorithms.*
200+
Addison-Wesley Professional. Third edition.
201+
"""
155202
function pseudo_divrem(f::_APL{S}, g::_APL{T}, algo) where {S,T}
156203
return _pseudo_divrem(
157204
algebraic_structure(MA.promote_operation(-, S, T)),
@@ -189,6 +236,8 @@ end
189236
190237
Return the pseudo remainder of `f` modulo `g` as defined in [Knu14, Algorithm R, p. 425].
191238
239+
See [`pseudo_divrem`](@ref) for more details.
240+
192241
[Knu14] Knuth, D.E., 2014.
193242
*Art of computer programming, volume 2: Seminumerical algorithms.*
194243
Addison-Wesley Professional. Third edition.
@@ -285,7 +334,7 @@ end
285334
"""
286335
rem_or_pseudo_rem(f::_APL, g::_APL, algo)
287336
288-
If the coefficient type is a field, return `rem`, otherwise, return [`pseudo_rem`](ref).
337+
If the coefficient type is a field, return `rem`, otherwise, return [`pseudo_rem`](@ref).
289338
"""
290339
function rem_or_pseudo_rem(f::_APL, g::_APL, algo)
291340
return MA.operate!!(rem_or_pseudo_rem, MA.mutable_copy(f), g, algo)

0 commit comments

Comments
 (0)