Skip to content

Commit 27d8139

Browse files
committed
Promote integer to rational for division
1 parent 14c11d0 commit 27d8139

File tree

3 files changed

+41
-4
lines changed

3 files changed

+41
-4
lines changed

docs/src/division.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,19 @@ Given a polynomial ``p`` and divisors ``d_1, \ldots, d_n``, one can find ``r`` a
88
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.
99
The `divrem` function returns ``(q, r)``.
1010
```@docs
11+
divrem
12+
div
13+
rem
1114
divides
1215
div_multiple
1316
```
1417

1518
Note that the coefficients of the polynomials need to be a field for `div`,
1619
`rem` and `divrem` to work.
20+
If the coefficient type is not a field, it is promoted to a field using [`promote_to_field`](@ref).
21+
```@docs
22+
promote_to_field
23+
```
1724
Alternatively, [`pseudo_rem`](@ref) or [`pseudo_divrem`](@ref) can be used
1825
instead as they do not require the coefficient type to be a field.
1926
```@docs
@@ -30,6 +37,7 @@ The same functions can be used with monomials and polynomials:
3037
```@docs
3138
gcd
3239
lcm
40+
<<<<<<< HEAD
3341
AbstractUnivariateGCDAlgorithm
3442
GeneralizedEuclideanAlgorithm
3543
SubresultantAlgorithm
@@ -42,4 +50,6 @@ univariate_gcd
4250
content
4351
primitive_part
4452
primitive_part_content
53+
=======
54+
>>>>>>> 1fe1303 (Promote integer to rational for division)
4555
```

src/division.jl

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,25 @@ struct Field end
6464
struct UniqueFactorizationDomain end
6565
const UFD = UniqueFactorizationDomain
6666

67+
"""
68+
promote_to_field(::Type{T})
69+
70+
Promote the type `T` to a field. For instance, `promote_to_field(T)` returns
71+
`Rational{T}` if `T` is an integer and `promote_to_field(T)` returns `RationalPoly{T}`
72+
if `T` is a polynomial.
73+
"""
74+
function promote_to_field end
75+
76+
function promote_to_field(::Type{T}) where {T<:Integer}
77+
return Rational{T}
78+
end
79+
function promote_to_field(::Type{T}) where {T<:_APL}
80+
return RationalPoly{T,T}
81+
end
82+
promote_to_field(::Type{T}) where {T} = T
83+
6784
algebraic_structure(::Type{<:Integer}) = UFD()
68-
algebraic_structure(::Type{<:AbstractPolynomialLike}) = UFD()
85+
algebraic_structure(::Type{<:_APL}) = UFD()
6986
# `Rational`, `AbstractFloat`, JuMP expressions, etc... are fields
7087
algebraic_structure(::Type) = Field()
7188
_field_absorb(::UFD, ::UFD) = UFD()
@@ -430,7 +447,11 @@ function MA.promote_operation(
430447
::Type{P},
431448
::Type{Q},
432449
) where {T,S,P<:_APL{T},Q<:_APL{S}}
433-
U = MA.promote_operation(/, T, S)
450+
U = MA.promote_operation(
451+
/,
452+
promote_to_field(T),
453+
promote_to_field(S),
454+
)
434455
# `promote_type(P, Q)` is needed for TypedPolynomials in case they use different variables
435456
return polynomial_type(promote_type(P, Q), MA.promote_operation(-, U, U))
436457
end

test/division.jl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,14 @@ end
5454

5555
function divrem_test()
5656
Mod.@polyvar x y
57-
@test (@inferred div(x * y^2 + 1, x * y + 1)) == y
58-
@test (@inferred rem(x * y^2 + 1, x * y + 1)) == -y + 1
57+
p = x * y^2 + 1
58+
q = x * y + 1
59+
@test typeof(div(p, q)) == MA.promote_operation(div, typeof(p), typeof(q))
60+
@test typeof(rem(p, q)) == MA.promote_operation(rem, typeof(p), typeof(q))
61+
@test coefficient_type(div(p, q)) == Rational{Int}
62+
@test coefficient_type(rem(p, q)) == Rational{Int}
63+
@test (@inferred div(p, q)) == y
64+
@test (@inferred rem(p, q)) == -y + 1
5965
@test (@inferred div(x * y^2 + x, y)) == x * y
6066
@test (@inferred rem(x * y^2 + x, y)) == x
6167
@test (@inferred rem(x^4 + x^3 + (1 + 1e-10) * x^2 + 1, x^2 + x + 1)) == 1

0 commit comments

Comments
 (0)