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