-
Notifications
You must be signed in to change notification settings - Fork 32
/
Copy pathfactorization.jl
69 lines (57 loc) · 1.99 KB
/
factorization.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
# implementation of a sorted dict (not optimized for speed) for storing
# the factorization of an integer
struct Factorization{T} <: AbstractDict{T, Int}
pe::Vector{Pair{T, Int}} # Prime-Exponent
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
f = Factorization{T}()
append!(f.pe, sort!(collect(d)))
f
end
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=>0, by=first)
(found > length(f.pe) || first(f.pe[found])) != p ? default : last(f.pe[found])
end
Base.getindex(f::Factorization, p) = get(f, p, 0)
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
insert!(f.pe, found, T(p)=>e)
else
f.pe[found] = T(p)=>e
end
f
end
"""
implements f[p] += e faster
"""
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
insert!(f.pe, found, T(p)=>e)
else
f.pe[found] = T(p)=>(last(f.pe[found])+e)
end
f
end
function increment!(f::AbstractDict, e::Int, p)
f[p] = get(f, p, 0) + e
return f
end
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]))