-
Notifications
You must be signed in to change notification settings - Fork 30
/
Copy pathrational.jl
86 lines (78 loc) · 3.26 KB
/
rational.jl
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
# TODO We should take gcd between numerator and denominator
struct RationalPoly{NT<:_APL,DT<:_APL}
num::NT
den::DT
end
# This constructor is called from LinearAlgebra in the method Matrix{T}(s::UniformScaling{Bool}, dims)
function RationalPoly{NT,DT}(x::Bool) where {NT,DT}
return ifelse(x, one(RationalPoly{NT,DT}), zero(RationalPoly{NT,DT}))
end
Base.numerator(r::RationalPoly) = r.num
Base.denominator(r::RationalPoly) = r.den
function Base.convert(
::Type{RationalPoly{NT,DT}},
q::RationalPoly{NT,DT},
) where {NT,DT}
return q
end
function Base.convert(
::Type{RationalPoly{NTout,DTout}},
q::RationalPoly{NTin,DTin},
) where {NTout,DTout,NTin,DTin}
return convert(NTout, q.num) / convert(DTout, q.den)
end
#function Base.convert(::Type{RationalPoly{NT, DT}}, p::NT) where {NT, DT}
# p / one(DT)
#end
function Base.convert(::Type{RationalPoly{NT,DT}}, p::_APL) where {NT,DT}
return convert(NT, p) / one(DT)
end
function Base.convert(::Type{RationalPoly{NT,DT}}, α) where {NT,DT}
return convert(NT, α) / one(DT)
#convert(RationalPoly{NT, DT}, convert(NT, α))
end
# This is called by the default implementation of `Base.oneunit`, still in Julia v1.8 at least
RationalPoly{NT,DT}(r::RationalPoly{NT,DT}) where {NT,DT} = r
Base.inv(r::RationalPoly) = r.den / r.num
Base.inv(p::_APL{T}) where {T} = one(T) / p
Base.:/(r::RationalPoly, p) = r.num / (r.den * p)
Base.:/(r::RationalPoly, p::_APL) = r.num / (r.den * p)
Base.:/(r::RationalPoly, s::RationalPoly) = (r.num * s.den) / (s.num * r.den)
function Base.:/(num::NT, den::DT) where {NT<:_APL,DT<:_APL}
return RationalPoly{NT,DT}(num, den)
end
function Base.:/(num, den::_APL)
return constant_term(num, den) / den
end
# Polynomial divided by coefficient is a polynomial not a rational polynomial
# (1/den) * num would not be correct in case of noncommutative coefficients
Base.:/(num::_APL, den) = map_coefficients(α -> α / den, num, nonzero = true)
function Base.:+(r::RationalPoly, s::RationalPoly)
return (r.num * s.den + r.den * s.num) / (r.den * s.den)
end
function _plus(r::RationalPoly, p)
return (p * r.den + r.num) / r.den
end
Base.:+(p::_APL, r::RationalPoly) = _plus(r, p)
Base.:+(r::RationalPoly, p::_APL) = _plus(r, p)
Base.:+(r::RationalPoly, α) = _plus(r, α)
Base.:+(α, r::RationalPoly) = _plus(r, α)
function Base.:-(r::RationalPoly, s::RationalPoly)
return (r.num * s.den - r.den * s.num) / (r.den * s.den)
end
_minus(p, s::RationalPoly) = (p * s.den - s.num) / s.den
_minus(s::RationalPoly, p) = (s.num - p * s.den) / s.den
Base.:-(p::_APL, r::RationalPoly) = _minus(p, r)
Base.:-(r::RationalPoly, p::_APL) = _minus(r, p)
Base.:-(r::RationalPoly, α) = _minus(r, α)
Base.:-(α, r::RationalPoly) = _minus(α, r)
Base.:-(r::RationalPoly) = (-r.num) / r.den
Base.:*(r::RationalPoly, s::RationalPoly) = (r.num * s.num) / (r.den * s.den)
Base.:*(p::_APL, r::RationalPoly) = (p * r.num) / r.den
Base.:*(r::RationalPoly, p::_APL) = (r.num * p) / r.den
Base.:*(α, r::RationalPoly) = (α * r.num) / r.den
Base.:*(r::RationalPoly, α) = (r.num * α) / r.den
Base.zero(r::RationalPoly) = zero(typeof(r))
Base.zero(::Type{RationalPoly{NT,DT}}) where {NT,DT} = zero(NT) / one(DT)
Base.one(r::RationalPoly) = one(typeof(r))
Base.one(::Type{RationalPoly{NT,DT}}) where {NT,DT} = one(NT) / one(DT)