Skip to content

Commit

Permalink
Merge pull request #18 from bionanoimaging/fix_type_tools
Browse files Browse the repository at this point in the history
added new methods to similar_arr_type to deal with SubArray ReshapedA…
  • Loading branch information
roflmaostc authored Jun 20, 2024
2 parents 3d33774 + 3c0b3f6 commit 7a6e941
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 31 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Manifest.toml
test/Manifest.toml
exmaples/Manifest.toml

docs/build/
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "NDTools"
uuid = "98581153-e998-4eef-8d0d-5ec2c052313d"
authors = ["Rainer Heintzmann <heintzmann@gmail.com>", "Felix Wechsler <fxw+git@mailbox.org>"]
version = "0.6.0"
version = "0.7.0"

[deps]
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Expand Down
62 changes: 38 additions & 24 deletions src/type_tools.jl
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
export real_arr_type, complex_arr_type, similar_arr_type

"""
real_arr_type(::Type{TA}) where {TA<:AbstractArray}
real_arr_type(::Type{TA}, dims::Val = Val(N)) where {TA<:AbstractArray}
returns the same array type but using `(real(eltype()))` as the element type
# Arguments
+ `TA`: The array type to convert to an eltype of `real(eltype(TA))`
+ `dims`: The number of dimensions of the returned array type
+ `dims`: The (optional) number of dimensions of the returned array type, default is Val(N) or Val(1) depending on whether the dimensions of the array are inferrable
# Example
```jldoctest
Expand All @@ -16,26 +16,26 @@ Vector{Float64} (alias for Array{Float64, 1})
julia> real_arr_type(Array{ComplexF64,3})
Array{Float64, 3}
julia> real_arr_type(Array{ComplexF64,3}, dims=4)
julia> real_arr_type(Array{ComplexF64,3}, dims=Val(4))
Array{Float64, 4}
```
"""
function real_arr_type(::Type{TA}; dims=N) where {T,N, TA<:AbstractArray{T,N}}
similar_arr_type(TA, dtype=real(eltype(TA)), dims=dims)
function real_arr_type(::Type{TA}, dims::Val=Val(N)) where {T,N, TA<:AbstractArray{T,N}}
similar_arr_type(TA, real(eltype(TA)), dims)
end

function real_arr_type(::Type{TA}; dims=1) where {TA<:AbstractArray}
similar_arr_type(TA, dtype=real(eltype(TA)), dims=dims)
function real_arr_type(::Type{TA}, dims::Val=Val(1)) where {TA<:AbstractArray}
similar_arr_type(TA, real(eltype(TA)), dims)
end

"""
complex_arr_type(::Type{TA}) where {TA<:AbstractArray}
complex_arr_type(::Type{TA}, dims::Val = VLa(N)) where {TA<:AbstractArray}
returns the same array type but using `(complex(eltype()))` as the element type
returns the same array type but using `(complex(eltype()))` as the element type, default is Val(N) or Val(1) depending on whether the dimensions of the array are inferrable
# Arguments
+ `TA`: The array type to convert to an eltype of `complex(eltype(TA))`
+ `dims`: The number of dimensions of the returned array type
+ `dims`: The (optional) number of dimensions of the returned array type
# Example
```jldoctest
Expand All @@ -45,28 +45,28 @@ Vector{ComplexF32} (alias for Array{Complex{Float32}, 1})
julia> complex_arr_type(Array{Float32,3})
Array{ComplexF32, 3}
julia> complex_arr_type(Array{Float32,3},dims=1)
julia> complex_arr_type(Array{Float32,3}, Val(1))
Vector{ComplexF32} (alias for Array{Complex{Float32}, 1})
```
"""
function complex_arr_type(::Type{TA}; dims=N) where {T,N, TA<:AbstractArray{T,N}}
similar_arr_type(TA, dtype=complex(eltype(TA)), dims=dims)
function complex_arr_type(::Type{TA}, dims::Val=Val(N)) where {T,N, TA<:AbstractArray{T,N}}
similar_arr_type(TA, complex(eltype(TA)), dims)
end

function complex_arr_type(::Type{TA}; dims=1) where {TA<:AbstractArray}
similar_arr_type(TA, dtype=complex(eltype(TA)), dims=dims)
function complex_arr_type(::Type{TA}, dims::Val=Val(1)) where {TA<:AbstractArray}
similar_arr_type(TA, complex(eltype(TA)), dims)
end


"""
similar_arr_type(::Type{TA}) where {TA<:AbstractArray}
similar_arr_type(::Type{TA}, , T2::Type=Type{T}, N2::Val=Val(N)) where {TA<:AbstractArray}
returns a similar array type but using as TA, but eltype and ndims can be changed.
# Arguments
+ `TA`: The array type to convert to an eltype of `complex(eltype(TA))`
+ `dims`: The number of dimensions of the returned array type
+ `dtype`: The `eltype()` of the returned array type.
+ `T2`: The `eltype()` of the returned array type. Use `eltype(TA)` to keep the same type. Default is `eltype(TA)`.
+ `N2`: The number of dimensions of the returned array type. Please specify this as a ::Val type to be type-stable. Default is Val(1).
# Example
Expand All @@ -77,14 +77,28 @@ Vector{ComplexF64} (alias for Array{Complex{Float64}, 1})
julia> similar_arr_type(Array{ComplexF64,3})
Array{ComplexF64, 3}
julia> similar_arr_type(Array{ComplexF64,3}, dims=2, dtype=Int)
julia> similar_arr_type(Array{ComplexF64,3}, Int, Val(2))
Matrix{Int64} (alias for Array{Int64, 2})
```
"""
function similar_arr_type(::Type{TA}; dims=N, dtype=T) where {T,N, TA<:AbstractArray{T,N}}
typeof(similar(TA(undef, ntuple(x->0, N)), dtype, ntuple(x->0, dims)))
function similar_arr_type(::Type{TA}, T2::Type=Type{T}, N2::Val=Val(N)) where {T, N, TA<:AbstractArray{T,N}}
typeof(similar(TA(undef, ntuple(x->0, N)), T2, ntuple(x->0, N2)))
end

function similar_arr_type(::Type{TA}; dims=1, dtype=eltype(TA)) where {TA<:AbstractArray}
typeof(similar(TA(undef), dtype, ntuple(x->0, dims)))

function similar_arr_type(::Type{TA}, T2::Type=Type{T}, N2::Val=Val(N)) where {T, N, P, I, L, TA<:SubArray{T,N,P,I,L}}
similar_arr_type(P, T2, N2)
end

function similar_arr_type(::Type{TA}, T2::Type=Type{T}, N2::Val=Val(N)) where {T, N, P, MI, TA<:Base.ReshapedArray{T,N,P,MI}}
similar_arr_type(P, T2, N2)
end

# note that T refers to the new type (if not explicitely specified) and therefore replaces the eltype of the array as defined by P
function similar_arr_type(::Type{TA}, T2::Type=Type{T}, N2::Val=Val(N)) where {T, N, O, P, B, TA<:Base.ReinterpretArray{T,N,O,P,B}}
similar_arr_type(P, T2, N2)
end

# specifically for not fully specified arrays
function similar_arr_type(::Type{TA}, T2::Type=eltype(TA), N2::Val=Val(1)) where {TA<:AbstractArray}
typeof(similar(TA(undef), T2, ntuple(x->0, N2)))
end
16 changes: 10 additions & 6 deletions test/type_tools.jl
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
@testset "Test Type Tools" begin
sz = (11,12)
@test real_arr_type(Array{Float32,2}) == Matrix{Float32}
@test complex_arr_type(Array{Float32,1}, dims=2) == Matrix{ComplexF32}
@test real_arr_type(Array{Float32}, dims=2) == Matrix{Float32}
@test complex_arr_type(Array{Float32}, dims=2) == Matrix{ComplexF32}
@test real_arr_type(Array{ComplexF64,2}, dims=1) == Vector{Float64}
@test complex_arr_type(Array{Float32,1}, Val(2)) == Matrix{ComplexF32}
@test real_arr_type(Array{Float32}, Val(2)) == Matrix{Float32}
@test complex_arr_type(Array{Float32}, Val(2)) == Matrix{ComplexF32}
@test real_arr_type(Array{ComplexF64,2}, Val(1)) == Vector{Float64}
@test complex_arr_type(Array{ComplexF64,1}) == Vector{ComplexF64}
@test similar_arr_type(Array{ComplexF64,1}, dims=2, dtype=Int) == Matrix{Int}
@test similar_arr_type(Array{ComplexF64}, dims=2, dtype=Int) == Matrix{Int}

@test similar_arr_type(Array{ComplexF64,1}, Int, Val(2)) == Matrix{Int}
@test similar_arr_type(Array{ComplexF64}, Float64, Val(2)) == Matrix{Float64}
@test similar_arr_type(typeof(view(ones(10,10),2:5,2:5)), Float64, Val(1)) == Vector{Float64}
@test similar_arr_type(typeof(reinterpret(Int, ones(10))), Float32, Val(2)) == Matrix{Float32}
@test similar_arr_type(typeof(reshape(view(ones(25),1:25), 5,5)), Int, Val(1)) == Vector{Int}
end

2 comments on commit 7a6e941

@roflmaostc
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator register

Release notes:

  • similar_arr_type,complex_arr_type and real_arr_type have new argument order and are type stable now.

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/109415

Tagging

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v0.7.0 -m "<description of version>" 7a6e94139bf472ad8c03ce747453051969a36bac
git push origin v0.7.0

Please sign in to comment.