Skip to content

Commit

Permalink
Merge branch 'simeonschaub-prepare_for_37573'
Browse files Browse the repository at this point in the history
  • Loading branch information
diegozea committed Apr 14, 2021
2 parents d9e669c + 5d28533 commit 7d63031
Show file tree
Hide file tree
Showing 5 changed files with 190 additions and 15 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "PairwiseListMatrices"
uuid = "f9da4da7-9382-5435-b973-175f5d8dfb32"
version = "0.9.0"
version = "0.10.0"

[deps]
DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab"
Expand Down
6 changes: 5 additions & 1 deletion src/PairwiseListMatrices.jl
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,12 @@ export PairwiseListMatrix,
writedlm,
apply2upper,
apply2list,
apply2diag
apply2diag,
@iteratelist,
@iteratediag,
@iterateupper

include("macros.jl")
include("pairwiselistmatrix.jl")
include("apply.jl")
include("plotrecipes.jl")
Expand Down
163 changes: 163 additions & 0 deletions src/macros.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
"""
The macro `@iteratelist` writes a `for` loop over the `list` but avoiding `getfield` calls
inside the loop. The first argument of the macro is the `PairwiseListMatrix` that is going
to be iterated and the second is the body of the loop.
In the body `list` will be the list field of the `PairwiseListMatrix` and `k` the index
over that list. Other variables are expanded in the current scope. You must not modify the
value of `k`.
```jldoctest
julia> using PairwiseListMatrices
julia> PLM = PairwiseListMatrix([1,2,3], false)
3×3 PairwiseListMatrix{Int64,false,Array{Int64,1}}:
0 1 2
1 0 3
2 3 0
julia> @iteratelist PLM println(list[k])
1
2
3
```
"""
macro iteratelist(plm, exp)
esc(quote
let list = $plm.list
for k in 1:length(list)
$exp
end
end
end)
end

"""
The macro `@iteratediag` writes a `for` loop over the `diag` field of a
`PairwiseListMatrix{T,false,VT}` but avoiding calls to `getfield` inside the loop. The first
argument of the macro is the `PairwiseListMatrix` that is going to be iterated and the
second is the body of the loop. In the body `diag` will be the diag field of the
`PairwiseListMatrix` and `k` the index over that vector.
Other variables are expanded in the current scope. You must not modify the value of `k`.
```jldoctest
julia> using PairwiseListMatrices
julia> PLM = PairwiseListMatrix([1,2,3], false)
3×3 PairwiseListMatrix{Int64,false,Array{Int64,1}}:
0 1 2
1 0 3
2 3 0
julia> @iteratediag PLM diag[k] += 10k
julia> PLM
3×3 PairwiseListMatrix{Int64,false,Array{Int64,1}}:
10 1 2
1 20 3
2 3 30
```
"""
macro iteratediag(plm, exp)
esc(quote
if !$hasdiagonal($plm)
local diag = $plm.diag
for k in 1:length(diag)
$exp
end
end
end)
end

"""
The macro `@iterateupper` iterates over the upper triangular part of the
`PairwiseListMatrix` that is given as first argument. The second argument should be
`true` if the diagonal need to be included in the iteration or `false` otherwise.
The last argument is the body of the loop, where `list` is the list and diag fields of
the `PairwiseListMatrix` and `k` is the index over that `list`.
You can also use the respective `i` and `j` indexes for that position `k` in the upper
triangular part of the matrix. Other variables are expanded in the current scope.
You must not modify the values of `i`, `j` or `k`.
```jldoctest
julia> using PairwiseListMatrices
julia> PLM = PairwiseListMatrix([1,2,3], true)
2×2 PairwiseListMatrix{Int64,true,Array{Int64,1}}:
1 2
2 3
julia> mat = zeros(Int, 2, 2)
2×2 Array{Int64,2}:
0 0
0 0
julia> let mat = mat # To avoid using global
@iterateupper PLM true mat[i,j] = list[k]
end
julia> mat
2×2 Array{Int64,2}:
1 2
0 3
```
"""
macro iterateupper(plm, use_diag, exp)
esc(quote
let N = $plm.nelements
local k, diag, list
if $hasdiagonal($plm)
if $use_diag
k = 0
list = $plm.list
for i in 1:N
for j in i:N
k += 1
$exp
end
end
else
k = 0
list = $plm.list
for i in 1:N
for j in i:N
k += 1
if i != j
$exp
end
end
end
end
else
if $use_diag
k = 0
diag = $plm.diag
list = $plm.list
for i in 1:N
for j in i:N
if i != j
k += 1
$exp
else
let list = diag, k = i
$exp
end
end
end
end
else
k = 0
list = $plm.list
for i in 1:(N-1)
for j in (i+1):N
k += 1
$exp
end
end
end
end
end
end)
end
22 changes: 9 additions & 13 deletions src/pairwiselistmatrix.jl
Original file line number Diff line number Diff line change
Expand Up @@ -527,9 +527,7 @@ end
bc::Base.Broadcast.Broadcasted{Nothing}) where {T, D, VT}
axes(dest) == axes(bc) || Base.Broadcast.throwdm(axes(dest), axes(bc))
bc_ = Base.Broadcast.preprocess(dest, bc)
apply2upper(dest; use_diag=true) do list, k, i, j
list[k] = bc_[CartesianIndex(i,j)] # slow: bc_ has a plm
end
@iterateupper dest true list[k] = bc_[CartesianIndex(i,j)] # slow: bc_ has a plm
return dest
end

Expand Down Expand Up @@ -1027,7 +1025,7 @@ julia> to_table(plm)
"3" "3" 0
julia> to_table(plm, diagonal=false)
3×3 Array{Any,2}:
3×3 Array{Any,2}:
"1" "2" 10
"1" "3" 20
"2" "3" 30
Expand All @@ -1038,11 +1036,11 @@ function to_table(plm::PairwiseListMatrix; diagonal::Bool = true, labels = getla
N = plm.nelements
table = Array{Any}(undef, diagonal ? div(N*(N+1),2) : div(N*(N-1),2), 3)
t = 0
apply2upper(plm; use_diag=diagonal) do list, k, i, j
t += 1
table[t, 1] = labels[i]
table[t, 2] = labels[j]
table[t, 3] = list[k]
@iterateupper plm diagonal begin
t += 1
table[t, 1] = labels[i]
table[t, 2] = labels[j]
table[t, 3] = list[k]
end
table
end
Expand Down Expand Up @@ -1094,7 +1092,7 @@ function to_dict(plm::PairwiseListMatrix{T,D,TV};
J = Array{String}(undef, L)
K = Array{T}(undef, L)
t = 0
apply2upper(plm; use_diag=diagonal) do list, k, i, j
@iterateupper plm diagonal begin
t += 1
I[t] = labels[i]
J[t] = labels[j]
Expand Down Expand Up @@ -1217,9 +1215,7 @@ function DelimitedFiles.writedlm(filename::String,
delim::Char = '\t',
labels::Vector{String} = getlabels(plm)) where {T,D,TV}
open(filename, "w") do fh
apply2upper(plm; use_diag=diagonal) do list, k, i, j
println(fh, labels[i], delim, labels[j], delim, list[k])
end
@iterateupper plm diagonal println(fh, labels[i], delim, labels[j], delim, list[k])
end
end

Expand Down
12 changes: 12 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -520,6 +520,9 @@ end
apply2list(PLMfalse) do list, k
@test(list[k] == list_values[k])
end

@iteratelist PLMtrue Main.@test(list[k] == list_values[k])
@iteratelist PLMfalse Main.@test(list[k] == list_values[k])

apply2diag(PLMfalse) do diag, k
@test(diag[k] == 0)
Expand All @@ -545,6 +548,15 @@ end
apply2upper(PLMfalse, use_diag=false) do list, k, i, j
list[k] = full_f[i, j]
end

@iterateupper PLMtrue true list[k] = list_values[k]
@iterateupper PLMfalse false list[k] = list_values[k]

@iterateupper PLMtrue true list[k] = full_t[i,j]
@iterateupper PLMtrue false list[k] = full_t[i,j]

@iterateupper PLMtrue true list[k] = full_f[i,j]
@iterateupper PLMfalse false list[k] = full_f[i,j]
end

@testset "IO" begin
Expand Down

0 comments on commit 7d63031

Please sign in to comment.