Skip to content

Commit a5b8931

Browse files
authored
Promote integer to rational for division (#296)
* Promote integer to rational for division * Fix format * Fixes * Fix
1 parent 14c11d0 commit a5b8931

File tree

3 files changed

+31
-4
lines changed

3 files changed

+31
-4
lines changed

docs/src/division.md

+4
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ div_multiple
1414

1515
Note that the coefficients of the polynomials need to be a field for `div`,
1616
`rem` and `divrem` to work.
17+
If the coefficient type is not a field, it is promoted to a field using [`promote_to_field`](@ref).
18+
```@docs
19+
promote_to_field
20+
```
1721
Alternatively, [`pseudo_rem`](@ref) or [`pseudo_divrem`](@ref) can be used
1822
instead as they do not require the coefficient type to be a field.
1923
```@docs

src/division.jl

+19-2
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,7 @@ 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(/, promote_to_field(T), promote_to_field(S))
434451
# `promote_type(P, Q)` is needed for TypedPolynomials in case they use different variables
435452
return polynomial_type(promote_type(P, Q), MA.promote_operation(-, U, U))
436453
end

test/division.jl

+8-2
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)