-
-
Save Ismael-VC/44240441e3c58d9da083 to your computer and use it in GitHub Desktop.
Julia implementation Fortran-like array with arbitrary starting indices, negative or zero.
Incurs a reasonable overhead vs. Base.Array, expected performance degradation should be strictly less than 2x.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Fortran-like array with arbitrary starting indices | |
# | |
# usage: | |
# | |
# julia> include("FArray.jl") | |
# size (generic function with 51 methods) | |
# | |
# julia> y = FArray(Float64, -1:1, -7:7, -128:512, -5:5, -1:1, -3:3, -2:2, -1:1); | |
# | |
# julia> y[-1,-7,-128,-5,-1,-3,-2,-1] = 14 | |
# 14 | |
# | |
# julia> y[-1,-7,-128,-5,-1,-3,-2,-1] += 5 | |
# 19.0 | |
# | |
# questions, found bugs and proposals for performance improvement please send to the author | |
# Alexander Samoilov ([email protected], [email protected]) | |
type FArray{T<:Number, N, A<:AbstractArray} <: AbstractArray | |
offsets::NTuple{N,Int} | |
array::A | |
o1::Int | |
o2::Int | |
o3::Int | |
o4::Int | |
o5::Int | |
function FArray(r::Range1{Int}) | |
array = Array(T, length(r)) | |
offs = (1 - minimum(r),) | |
new(offs, array, offs[1]) | |
end | |
function FArray(r1::Range1{Int}, r2::Range1{Int}) | |
dims = (length(r1), length(r2)) | |
array = Array(T, dims) | |
offs = (1 - minimum(r1), 1 - minimum(r2)) | |
new(offs, array, offs[1], offs[2]) | |
end | |
function FArray(r1::Range1{Int}, r2::Range1{Int}, r3::Range1{Int}) | |
dims = (length(r1), length(r2), length(r3)) | |
array = Array(T, dims) | |
offs = (1 - minimum(r1), 1 - minimum(r2), 1 - minimum(r3)) | |
new(offs, array, offs[1], offs[2], offs[3]) | |
end | |
function FArray(r1::Range1{Int}, r2::Range1{Int}, r3::Range1{Int}, r4::Range1{Int}) | |
dims = (length(r1), length(r2), length(r3), length(r4)) | |
array = Array(T, dims) | |
offs = (1 - minimum(r1), 1 - minimum(r2), 1 - minimum(r3), 1 - minimum(r4)) | |
new(offs, array, offs[1], offs[2], offs[3], offs[4]) | |
end | |
function FArray(r1::Range1{Int}, r2::Range1{Int}, r3::Range1{Int}, r4::Range1{Int}, r5::Range1{Int}) | |
dims = (length(r1), length(r2), length(r3), length(r4), length(r5)) | |
array = Array(T, dims) | |
offs = (1 - minimum(r1), 1 - minimum(r2), 1 - minimum(r3), 1 - minimum(r4), 1 - minimum(r5)) | |
new(offs, array, offs[1], offs[2], offs[3], offs[4], offs[5]) | |
end | |
function FArray(r::Range1{Int}...) | |
dims = map((x) -> length(x), r) | |
array = Array(T, dims) | |
offs = map((x) -> 1 - minimum(x), r) | |
new(offs, array) | |
end | |
end | |
FArray(T, r::Range1{Int}...) = FArray{T, length(r,), Array{T, length(r,)}}(r...) | |
getindex{T<:Number}(FA::FArray{T,1}, i1::Int) = FA.array[i1+FA.o1] | |
getindex{T<:Number}(FA::FArray{T,2}, i1::Int, i2::Int) = FA.array[i1+FA.o1, i2+FA.o2] | |
getindex{T<:Number}(FA::FArray{T,3}, i1::Int, i2::Int, i3::Int) = FA.array[i1+FA.o1, i2+FA.o2, i3+FA.o3] | |
getindex{T<:Number}(FA::FArray{T,4}, i1::Int, i2::Int, i3::Int, i4::Int) = FA.array[i1+FA.o1, i2+FA.o2, i3+FA.o3, i4+FA.o4] | |
getindex{T<:Number}(FA::FArray{T,5}, i1::Int, i2::Int, i3::Int, i4::Int, i5::Int) = FA.array[i1+FA.o1, i2+FA.o2, i3+FA.o3, i4+FA.o4, i5+FA.o5] | |
# a generic not very efficient case | |
getindex{T<:Number,N}(FA::FArray{T,N}, I::Int...) = let ind = [I[i] + FA.offsets[i] for i = 1:length(I)]; return FA.array[ind...] end | |
setindex!{T<:Number}(FA::FArray{T,1}, x, i1::Int) = arrayset(FA.array, convert(T,x), i1+FA.o1) | |
setindex!{T<:Number}(FA::FArray{T,2}, x, i1::Int, i2::Int) = arrayset(FA.array, convert(T,x), i1+FA.o1, i2+FA.o2) | |
setindex!{T<:Number}(FA::FArray{T,3}, x, i1::Int, i2::Int, i3::Int) = arrayset(FA.array, convert(T,x), i1+FA.o1, i2+FA.o2, i3+FA.o3) | |
setindex!{T<:Number}(FA::FArray{T,4}, x, i1::Int, i2::Int, i3::Int, i4::Int) = arrayset(FA.array, convert(T,x), i1+FA.o1, i2+FA.o2, i3+FA.o3, i4+FA.o4) | |
setindex!{T<:Number}(FA::FArray{T,5}, x, i1::Int, i2::Int, i3::Int, i4::Int, i5::Int) = arrayset(FA.array, convert(T,x), i1+FA.o1, i2+FA.o2, i3+FA.o3, i4+FA.o4, i5+FA.o5) | |
# a generic not very efficient case | |
setindex!{T<:Number,N}(FA::FArray{T,N}, x, I::Int...) = let ind = [I[i] + FA.offsets[i] for i = 1:length(I)]; arrayset(FA.array, convert(T,x), ind...) end | |
Base.print(a::FArray) = Base.print(a.array) | |
Base.display(a::FArray) = Base.display(a.array) | |
Base.size(a::FArray) = arraysize(a.array) | |
Base.size(a::FArray, d) = arraysize(a.array, d) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment