Skip to content

Commit

Permalink
Refactor code
Browse files Browse the repository at this point in the history
  • Loading branch information
laschuet committed Apr 28, 2020
1 parent 5b0c483 commit 511fb00
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 97 deletions.
1 change: 1 addition & 0 deletions src/DifferencesBase.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ using SparseArrays
import Base: ==, diff, hash, replace, replace!

export
AbstractDifference,
MatrixDifference,
SetDifference,
added,
Expand Down
86 changes: 9 additions & 77 deletions src/difference.jl
Original file line number Diff line number Diff line change
@@ -1,88 +1,20 @@
"""
diff(A::AbstractMatrix, B::AbstractMatrix)
AbstractDifference
Compute the difference between matrix `A` and matrix `B`, and return a tuple
containing the elements that have been modified, added (per row and column), and
removed (per row and column).
Supertype for differences.
"""
function diff(A::AbstractMatrix, B::AbstractMatrix)
iadict = OrderedDict{Int,Int}(i => i for i = 1:size(A, 1))
jadict = OrderedDict{Int,Int}(j => j for j = 1:size(A, 2))
ibdict = OrderedDict{Int,Int}(i => i for i = 1:size(B, 1))
jbdict = OrderedDict{Int,Int}(j => j for j = 1:size(B, 2))
return _diff(A, B, iadict, jadict, ibdict, jbdict)
end
abstract type AbstractDifference end

"""
diff(A::AbstractMatrix, B::AbstractMatrix, ia::AbstractVector, ja::AbstractVector, ib::AbstractVector, jb::AbstractVector)
added(a::AbstractDifference)
Like [`diff`](@ref), but provide integer vectors that number the rows and
columns of the matrices `A` and `B`. The vector `ia` represents the row numbers
of `A`, and the vector `jb` represents the column numbers of `B` etc. The
position of each vector element refers to the row index (or column index
respectively) of `A` or `B`.
Access the added elements.
"""
function diff(A::AbstractMatrix, B::AbstractMatrix, ia::AbstractVector,
ja::AbstractVector, ib::AbstractVector, jb::AbstractVector)
iadict = OrderedDict(zip(ia, 1:length(ia)))
jadict = OrderedDict(zip(ja, 1:length(ja)))
ibdict = OrderedDict(zip(ib, 1:length(ib)))
jbdict = OrderedDict(zip(jb, 1:length(jb)))
return _diff(A, B, iadict, jadict, ibdict, jbdict)
end

# Core matrix difference implementation
function _diff(A::AbstractMatrix, B::AbstractMatrix, ia::OrderedDict,
ja::OrderedDict, ib::OrderedDict, jb::OrderedDict)
T = promote_type(eltype(A), eltype(B))
modvals = sparse([], [], T[])
addvals = view(Vector{T}(undef, 0), :)
remvals = view(Vector{T}(undef, 0), :)

if size(A) == (0, 0) || size(B) == (0, 0)
return modvals, addvals, remvals
end

iakeys = collect(keys(ia))
jakeys = collect(keys(ja))
ibkeys = collect(keys(ib))
jbkeys = collect(keys(jb))

# Compute modified values
i = intersect(iakeys, ibkeys)
j = intersect(jakeys, jbkeys)
ia2 = replace(i, ia)
ja2 = replace(j, ja)
ib2 = replace(i, ib)
jb2 = replace(j, jb)
modvals = sparse(view(A, ia2, ja2) - view(B, ib2, jb2))

# Compute added values
indicesb = CartesianIndices(B)
modindicesb = CartesianIndex.(Iterators.product(ib2, jb2))
addindices = setdiff(indicesb, modindicesb)
addvals = view(B, addindices)

# Compute removed values
indicesa = CartesianIndices(A)
modindicesa = CartesianIndex.(Iterators.product(ia2, ja2))
remindices = setdiff(indicesa, modindicesa)
remvals = view(A, remindices)

return modvals, addvals, remvals
end
added(a::AbstractDifference) = a.addvals

"""
diff(a::AbstractSet, b::AbstractSet)
Compute the difference between set `a` and set `b`, and return a tuple
containing the unique elements that have been shared, added, and removed.
removed(a::AbstractDifference)
# Examples
```jldoctest
julia> diff(Set([1, 2, 3, 3]), Set([4, 2, 1]))
(Set([1, 2]), Set([4]), Set([3]))
```
Access the removed elements.
"""
diff(a::AbstractSet, b::AbstractSet) =
intersect(a, b), setdiff(b, a), setdiff(a, b)
removed(a::AbstractDifference) = a.remvals
76 changes: 68 additions & 8 deletions src/matrix.jl
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
"""
MatrixDifference{Tm<:AbstracArray,Ta<:AbstractArray,Tr<:AbstractArray}
MatrixDifference{Tm<:AbstracArray,Ta<:AbstractArray,Tr<:AbstractArray} <: AbstractDifference
Matrix difference.
"""
struct MatrixDifference{Tm<:AbstractArray,Ta<:AbstractArray,Tr<:AbstractArray}
struct MatrixDifference{Tm<:AbstractArray,Ta<:AbstractArray,Tr<:AbstractArray} <: AbstractDifference
modvals::Tm
addvals::Ta
remvals::Tr
Expand All @@ -26,15 +26,75 @@ Access the modified elements.
modified(a::MatrixDifference) = a.modvals

"""
added(a::MatrixDifference)
diff(A::AbstractMatrix, B::AbstractMatrix)
Access the added elements.
Compute the difference between matrix `A` and matrix `B`, and return a tuple
containing the elements that have been modified, added (per row and column), and
removed (per row and column).
"""
added(a::MatrixDifference) = a.addvals
function diff(A::AbstractMatrix, B::AbstractMatrix)
iadict = OrderedDict{Int,Int}(i => i for i = 1:size(A, 1))
jadict = OrderedDict{Int,Int}(j => j for j = 1:size(A, 2))
ibdict = OrderedDict{Int,Int}(i => i for i = 1:size(B, 1))
jbdict = OrderedDict{Int,Int}(j => j for j = 1:size(B, 2))
return _diff(A, B, iadict, jadict, ibdict, jbdict)
end

"""
removed(a::MatrixDifference)
diff(A::AbstractMatrix, B::AbstractMatrix, ia::AbstractVector, ja::AbstractVector, ib::AbstractVector, jb::AbstractVector)
Access the removed elements.
Like [`diff`](@ref), but provide integer vectors that number the rows and
columns of the matrices `A` and `B`. The vector `ia` represents the row numbers
of `A`, and the vector `jb` represents the column numbers of `B` etc. The
position of each vector element refers to the row index (or column index
respectively) of `A` or `B`.
"""
removed(a::MatrixDifference) = a.remvals
function diff(A::AbstractMatrix, B::AbstractMatrix, ia::AbstractVector,
ja::AbstractVector, ib::AbstractVector, jb::AbstractVector)
iadict = OrderedDict(zip(ia, 1:length(ia)))
jadict = OrderedDict(zip(ja, 1:length(ja)))
ibdict = OrderedDict(zip(ib, 1:length(ib)))
jbdict = OrderedDict(zip(jb, 1:length(jb)))
return _diff(A, B, iadict, jadict, ibdict, jbdict)
end

# Core matrix difference implementation
function _diff(A::AbstractMatrix, B::AbstractMatrix, ia::OrderedDict,
ja::OrderedDict, ib::OrderedDict, jb::OrderedDict)
T = promote_type(eltype(A), eltype(B))
modvals = sparse([], [], T[])
addvals = view(Vector{T}(undef, 0), :)
remvals = view(Vector{T}(undef, 0), :)

if size(A) == (0, 0) || size(B) == (0, 0)
return modvals, addvals, remvals
end

iakeys = collect(keys(ia))
jakeys = collect(keys(ja))
ibkeys = collect(keys(ib))
jbkeys = collect(keys(jb))

# Compute modified values
i = intersect(iakeys, ibkeys)
j = intersect(jakeys, jbkeys)
ia2 = replace(i, ia)
ja2 = replace(j, ja)
ib2 = replace(i, ib)
jb2 = replace(j, jb)
modvals = sparse(view(A, ia2, ja2) - view(B, ib2, jb2))

# Compute added values
indicesb = CartesianIndices(B)
modindicesb = CartesianIndex.(Iterators.product(ib2, jb2))
addindices = setdiff(indicesb, modindicesb)
addvals = view(B, addindices)

# Compute removed values
indicesa = CartesianIndices(A)
modindicesa = CartesianIndex.(Iterators.product(ia2, ja2))
remindices = setdiff(indicesa, modindicesa)
remvals = view(A, remindices)

return modvals, addvals, remvals
end
25 changes: 13 additions & 12 deletions src/set.jl
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
"""
SetDifference{T}
SetDifference{T} <: AbstractDifference
Set difference.
"""
struct SetDifference{T}
struct SetDifference{T} <: AbstractDifference
comvals::Set{T}
addvals::Set{T}
remvals::Set{T}
Expand All @@ -23,20 +23,21 @@ hash(a::SetDifference, h::UInt) =
"""
common(a::SetDifference)
Access the common elements.
Access the modified elements.
"""
common(a::SetDifference) = a.comvals

"""
added(a::SetDifference)
diff(a::AbstractSet, b::AbstractSet)
Access the added elements.
"""
added(a::SetDifference) = a.addvals

"""
removed(a::SetDifference)
Compute the difference between set `a` and set `b`, and return a tuple
containing the unique elements that have been shared, added, and removed.
Access the removed elements.
# Examples
```jldoctest
julia> diff(Set([1, 2, 3, 3]), Set([4, 2, 1]))
(Set([1, 2]), Set([4]), Set([3]))
```
"""
removed(a::SetDifference) = a.remvals
diff(a::AbstractSet, b::AbstractSet) =
intersect(a, b), setdiff(b, a), setdiff(a, b)

0 comments on commit 511fb00

Please sign in to comment.