Skip to content

Instantly share code, notes, and snippets.

@SimonDanisch
Created August 30, 2014 16:30
Show Gist options
  • Save SimonDanisch/23f86fbb618cdfabacee to your computer and use it in GitHub Desktop.
Save SimonDanisch/23f86fbb618cdfabacee to your computer and use it in GitHub Desktop.
import Base: eltype, getindex, length, ndims, size, convert, vcat
## Abstract Types
abstract AbstractFixedArray{T,N,SZ} <: DenseArray{T,N}
abstract AbstractMutableFixedArray{T,N,SZ} <: AbstractFixedArray{T,N,SZ}
abstract AbstractImmutableFixedArray{T,N,SZ} <: AbstractFixedArray{T,N,SZ}
typealias FixedVector{T, L} AbstractFixedArray{T,1,(L,)}
typealias FixedMatrix{T, RD, CD} AbstractFixedArray{T,2,(RD,CD)}
typealias ImmutableFixedVector{T, L} AbstractImmutableFixedArray{T,1,(L,)}
typealias MutableFixedVector{T, L} AbstractMutableFixedArray{T,1,(L,)}
typealias ImmutableFixedMatrix{T, RD, CD} AbstractImmutableFixedArray{T,2,(RD,CD)}
typealias MutableFixedMatrix{T, RD, CD} AbstractMutableFixedArray{T,2,(RD,CD)}
## Utility functions
eltype{T,N,SZ}(A::AbstractFixedArray{T,N,SZ}) = T
length{T,N,SZ}(A::AbstractFixedArray{T,N,SZ}) = prod(SZ)
# this is extremely ugly, I think, but as you have fixed size arrays, you might as well want to know the length of a type
length{T <: AbstractFixedArray}(A::Type{T}) = prod(super(T).parameters[3])
ndims{T,N,SZ}(A::AbstractFixedArray{T,N,SZ}) = N
size{T,N,SZ}(A::AbstractFixedArray{T,N,SZ}) = SZ
size{T,N,SZ}(A::AbstractFixedArray{T,N,SZ}, d::Integer) = SZ[d]
getindex{T,SZ}(A::AbstractFixedArray{T,1,SZ}, i::Integer) = getfield(A, i)
getindex{T,SZ}(A::AbstractFixedArray{T,2,SZ}, i::Integer, j::Integer) = getfield(getfield(A, i), j)
getindex{T,SZ}(A::AbstractFixedArray{T,2,SZ}, i::Integer) = getfield(getfield(A, i % SZ[1]), div(i, SZ[1]))
# Array for mutable FixedSizeArrays with c memory alignement
immutable MemoryAlignedArray{Eltype <: AbstractMutableFixedArray, T}
data::Array{T}
end
Base.pointer(a::MemoryAlignedArray) = pointer(a.data)
# I just implemented getindex only for vectors out of prototyping lazyness
function getindex{Eltype, T}(A::MemoryAlignedArray{Eltype, T}, i::Integer)
L = length(Eltype)
ptr = convert(Ptr{Eltype}, pointer(A.data[(i*L)-(L-1):i*L]))
return unsafe_load(ptr, 1)
end
# To achieve memory alignement, vcat creates a MemoryAlignedArray
function Base.vcat{T,L}(A::MutableFixedVector{T, L}...)
ts = L*length(A)
result = Array(T, ts)
Tvector = typeof(first(A))
i = 1
for elem in A
for j=0:L-1
result[i+j] = elem[j+1]
end
i += 3
end
return MemoryAlignedArray{Tvector, T}(result)
end
#Vcat for fixed size arrays should not concatenate
function Base.vcat{T,N,SZ}(A::AbstractFixedArray{T,N,SZ}...)
result = Array(typeof(first(A)), length(A))
println(result)
for (i,elem) in enumerate(A)
result[i] = elem
end
return result
end
# It would be nice, if one could determine if the types are convertible via the function signature.
# But dispatch with abstract types doesn't work when they're a parameter. Any other way to do this?
function Base.convert{EltypeA <: AbstractFixedArray, EltypeB <: AbstractFixedArray}(t::Type{EltypeA}, a::Array{EltypeB})
#TODO type check
ptr = convert(Ptr{t}, pointer(a))
return pointer_to_array(ptr, size(a))
end
function Base.convert{EltypeA <: AbstractFixedArray, EltypeB <: Real}(t::Type{EltypeA}, a::Array{EltypeB})
#TODO type check
ptr = convert(Ptr{t}, pointer(a))
return unsafe_load(ptr, 1)
end
##########################
# Example fixed size vectors, which can be created with a macro or by the user:
immutable Vec3I{T} <: ImmutableFixedVector{T, 3}
x::T
y::T
z::T
end
immutable Mat3I{T} <: ImmutableFixedMatrix{T, 3, 3}
r1::Vec3I{T}
r2::Vec3I{T}
r3::Vec3I{T}
end
immutable RGB{T} <: ImmutableFixedVector{T, 3}
x::T
y::T
z::T
end
type Vec3M{T} <: MutableFixedVector{T, 3}
x::T
y::T
z::T
end
println("vcat:")
@show a = [Vec3M(1,2,3), Vec3M(77,23,3), Vec3M(1,88,3)]
println("Indexing:")
@show typeof(a[1])
@show a[2]
@show a[3]
println("Memory alignemt:")
ptr = convert(Ptr{Int}, pointer(a))
unsafe_store!(ptr, 2332, 1)
for i=1:3*3
print(unsafe_load(ptr, i), " ")
end
println()
println(a)
println("converting between fixed size arrays: ")
@show colors = [RGB(2,3,4), RGB(12,23,22)]
converted = convert(Vec3I{Int}, colors)
println("converted: ", typeof(converted), ": ", converted)
println("Conversion to a fixed size array:")
@show mat3 = convert(Mat3I{Float32}, eye(Float32, 3,3))
println(typeof(mat3))
println("matrix indexing: ")
@show mat3[1,3]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment