Skip to content

Commit

Permalink
Merge pull request #127 from jmichel7/master
Browse files Browse the repository at this point in the history
suppressed Integer annotation on Factorization; fixed bug in calls of…
  • Loading branch information
oscardssmith authored Jul 3, 2023
2 parents 8c20fb3 + 42b4d92 commit a26041e
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 13 deletions.
2 changes: 1 addition & 1 deletion src/Primes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1012,7 +1012,7 @@ end
Return a vector with the positive divisors of the number whose factorization is `f`.
Divisors are sorted lexicographically, rather than numerically.
"""
function divisors(f::Factorization{T}) where {T<:Integer}
function divisors(f::Factorization{T}) where T
sgn = sign(f)
if iszero(sgn) # n == 0
return T[]
Expand Down
24 changes: 12 additions & 12 deletions src/factorization.jl
Original file line number Diff line number Diff line change
@@ -1,37 +1,37 @@
# implementation of a sorted dict (not optimized for speed) for storing
# the factorization of an integer

struct Factorization{T<:Integer} <: AbstractDict{T, Int}
struct Factorization{T} <: AbstractDict{T, Int}
pe::Vector{Pair{T, Int}} # Prime-Exponent

function Factorization{T}() where {T<:Integer}
function Factorization{T}() where T
# preallocates enough space that numbers smaller than 2310 won't need to resize
v = Vector{Pair{T, Int}}(undef, 4)
empty!(v)
new{T}(v)
end
end

function Factorization{T}(d::AbstractDict) where T<:Integer
function Factorization{T}(d::AbstractDict) where T
f = Factorization{T}()
append!(f.pe, sort!(collect(d)))
f
end

Factorization(d::AbstractDict{T}) where {T<:Integer} = Factorization{T}(d)
Factorization(d::AbstractDict{T}) where T = Factorization{T}(d)
Base.convert(::Type{Factorization}, d::AbstractDict) = Factorization(d)

Base.iterate(f::Factorization, state...) = iterate(f.pe, state...)

function Base.get(f::Factorization, p, default)
found = searchsortedfirst(f.pe, p, by=first)
found = searchsortedfirst(f.pe, p=>0, by=first)
(found > length(f.pe) || first(f.pe[found])) != p ? default : last(f.pe[found])
end

Base.getindex(f::Factorization, p::Integer) = get(f, p, 0)
Base.getindex(f::Factorization, p) = get(f, p, 0)

function Base.setindex!(f::Factorization{T}, e::Int, p::Integer) where T
found = searchsortedfirst(f.pe, p, by=first)
function Base.setindex!(f::Factorization{T}, e::Int, p) where T
found = searchsortedfirst(f.pe, p=>0, by=first)
if found > length(f.pe)
push!(f.pe, T(p)=>e)
elseif first(f.pe[found]) != p
Expand All @@ -45,8 +45,8 @@ end
"""
impliments f[p] += e faster
"""
function increment!(f::Factorization{T}, e::Int, p::Integer) where T
found = searchsortedfirst(f.pe, p, by=first)
function increment!(f::Factorization{T}, e::Int, p) where T
found = searchsortedfirst(f.pe, p=>0, by=first)
if found > length(f.pe)
push!(f.pe, T(p)=>e)
elseif first(f.pe[found]) != p
Expand All @@ -56,7 +56,7 @@ function increment!(f::Factorization{T}, e::Int, p::Integer) where T
end
f
end
function increment!(f::AbstractDict, e::Int, p::Integer)
function increment!(f::AbstractDict, e::Int, p)
f[p] = get(f, p, 0) + e
return f
end
Expand All @@ -66,4 +66,4 @@ Base.length(f::Factorization) = length(f.pe)
Base.show(io::IO, ::MIME{Symbol("text/plain")}, f::Factorization) =
join(io, isempty(f) ? "1" : [(e == 1 ? "$p" : "$p^$e") for (p,e) in f.pe], " * ")

Base.sign(f::Factorization) = isempty(f.pe) ? one(keytype(f)) : sign(first(f.pe[1]))
Base.sign(f::Factorization) = isempty(f.pe) ? one(keytype(f)) : sign(first(f.pe[1]))
11 changes: 11 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,17 @@ for T = (Int, UInt, BigInt)
@test issorted(f.pe)
end

d = Dict(:a=>1,:b=>2)
f = Factorization(d)
@test f == d == Dict(f) == convert(Factorization, d)
@test collect(f) == sort!(collect(d)) # test start/next/done
@test length(f) == length(d)
@test get(f, :c, nothing) === nothing
@test f[:c] == 0
@test f[:a] == 1
f[:c] = 1
@test get(f, :c, 0) == 1

# dumb implementation of Euler totient for correctness tests
ϕ(n) = count(m -> gcd(n, m) == 1, 1:n)

Expand Down

0 comments on commit a26041e

Please sign in to comment.