Created
August 30, 2014 16:30
-
-
Save SimonDanisch/23f86fbb618cdfabacee to your computer and use it in GitHub Desktop.
This file contains hidden or 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
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