Conjuntos similares a Fortran, como FArray (Float64, -1: 1, -7: 7, -128: 512) en Julia

En general, tener una matriz basada en 1 para Julia es una buena decisión, pero a veces es conveniente tener una matriz similar a Fortran con índices que abarquen algunos subrangos de ℤ:

julia> x = FArray(Float64, -1:1,-7:7,-128:512)

donde seria util:

en los códigos que acompañan al libro Solución numérica de ecuaciones diferenciales parciales hiperbólicas del prof. John A. Trangenstein estos índices negativos se usan intensivamente para las células fantasma en condiciones de contorno. Lo mismo es cierto para Clawpack (significa "Paquete de leyes de conservación") por el prof. Randall j. Levequehttp://depts.washington.edu/clawpack/y hay muchos otros códigos donde tales índices serían naturales. Por lo tanto, tal clase auxiliar sería útil para la traducción rápida de tales códigos.

Acabo de comenzar a implementar un tipo auxiliar de este tipo, pero como soy bastante nuevo en Julia, su ayuda sería muy apreciada.

Comencé con:

type FArray
    ranges
    array::Array
    function FArray(T, r::Range1{Int}...)
        dims = map((x) -> length(x), r)
        array = Array(T, dims)
        new(r, array)
    end
end

Salida:

julia> include ("FortranArray.jl")
julia> x = FArray(Float64, -1:1,-7:7,-128:512)
FArray((-1:1,-7:7,-128:512),3x15x641 Array{Float64,3}:
[:, :, 1] =
6.90321e-310  2.6821e-316   1.96042e-316  0.0  0.0  0.0  9.84474e-317  …  1.83233e-316  2.63285e-316  0.0           9.61618e-317  0.0        
6.90321e-310  6.32404e-322  2.63285e-316  0.0  0.0  0.0  2.63292e-316     2.67975e-316
...
[:, :, 2] =
...

Como soy completamente nuevo en Julia, cualquier recomendación, especialmente la que lleve a ser más eficiente, sería muy apreciada.

[Editar]

El tema ha sido discutido aquí:

https://groups.google.com/forum/#!topic/julia-dev/NOF6MA6tb9Y

Durante la discusión, se elaboraron dos formas de hacer arreglos de Julia con base arbitraria: basado en SubArray, el uso de la muestra es con una función auxiliar:

function farray(T, r::Range1{Int64}...)
    dims = map((x) -> length(x), r)
    array = Array(T, dims)
    sub_indices = map((x) -> -minimum(x) + 2 : maximum(x), r)
    sub(array, sub_indices)
end

julia> y[-1,-7,-128] = 777
777

julia> y[-1,-7,-128] + 33
810.0

julia> y[-2,-7,-128]
ERROR: BoundsError()
 in getindex at subarray.jl:200

julia> y[2,-7,-128]
2.3977385e-316

Tenga en cuenta que los límites no se verifican completamente más detalles aquí:https://github.com/JuliaLang/julia/issues/4044

En este momento, SubArray tiene problemas de rendimiento, pero eventualmente su rendimiento podría mejorar, vea también:

https://github.com/JuliaLang/julia/issues/5117

https://github.com/JuliaLang/julia/issues/3496

Otro enfoque que tiene mejor desempeño en este momento, además de verificar ambos límites:

type FArray{T<:Number, N, A<:AbstractArray} <: AbstractArray

    ranges
    offsets::NTuple{N,Int}
    array::A

    function FArray(r::Range1{Int}...)
        dims = map((x) -> length(x), r)
        array = Array(T, dims)
        offs = map((x) -> 1 - minimum(x), r)
        new(r, offs, array)
    end
end

FArray(T, r::Range1{Int}...) = FArray{T, length(r,), Array{T, length(r,)}}(r...)

getindex{T<:Number}(FA::FArray{T}, i1::Int) = FA.array[i1+FA.offsets[1]]
getindex{T<:Number}(FA::FArray{T}, i1::Int, i2::Int) = FA.array[i1+FA.offsets[1], i2+FA.offsets[2]]
getindex{T<:Number}(FA::FArray{T}, i1::Int, i2::Int, i3::Int) = FA.array[i1+FA.offsets[1], i2+FA.offsets[2], i3+FA.offsets[3]]

setindex!{T}(FA::FArray{T}, x, i1::Int) = arrayset(FA.array, convert(T,x), i1+FA.offsets[1])
setindex!{T}(FA::FArray{T}, x, i1::Int, i2::Int) = arrayset(FA.array, convert(T,x), i1+FA.offsets[1], i2+FA.offsets[2])
setindex!{T}(FA::FArray{T}, x, i1::Int, i2::Int, i3::Int) = arrayset(FA.array, convert(T,x), i1+FA.offsets[1], i2+FA.offsets[2], i3+FA.offsets[3])

getindex y setindex! Los métodos para FArray se inspiraron en el código base / array.jl.

Casos de uso:

julia> y = FArray(Float64, -1:1,-7:7,-128:512);

julia> y[-1,-7,-128] = 777
777

julia> y[-1,-7,-128] + 33
810.0

julia> y[-1,2,3]
0.0

julia> y[-2,-7,-128]
ERROR: BoundsError()
 in getindex at FortranArray.jl:27

julia> y[2,-7,-128]
ERROR: BoundsError()
 in getindex at FortranArray.jl:27

Respuestas a la pregunta(1)

Su respuesta a la pregunta