Skip to content
This repository was archived by the owner on Nov 22, 2023. It is now read-only.

Commit

Permalink
Merge pull request #29 from JuliaGeometry/sjk/getindex
Browse files Browse the repository at this point in the history
Improve codegen for getindex(::Array, ::Face)
  • Loading branch information
sjkelly committed Dec 5, 2015
2 parents 4106f81 + 3246b45 commit 762f23a
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/GeometryTypes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ include("display.jl")
include("slice.jl")
include("decompose.jl")
include("deprecated.jl")
include("checkbounds.jl")

export AABB,
AbsoluteRectangle,
Expand Down
19 changes: 19 additions & 0 deletions src/checkbounds.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"""
Check the `Face` indices to ensure they are in the bounds of the vertex
array of the `AbstractMesh`.
"""
function Base.checkbounds{VT,FT,FD,FO}(m::AbstractMesh{VT,Face{FD,FT,FO}})
isempty(faces(m)) && return true # nothing to worry about I guess

# index max and min
const i = one(FO) + FO # normalize face offset
s = length(vertices(m)) + FO

for face in faces(m)
# I hope this is unrolled
for elt in face
i <= elt && elt <= s || return false
end
end
return true
end
19 changes: 17 additions & 2 deletions src/faces.jl
Original file line number Diff line number Diff line change
@@ -1,6 +1,21 @@
function getindex{T,N,FD,FT,Offset}(a::Array{T,N}, i::Face{FD, FT, Offset})
a[[(map(Int,i)-Offset)...]]
"""
Given an Array, `a`, and a face, `f`, return a tuple of numbers
interpreting the values and offset of the face as indices into `A`.
Note: This is not bounds checked. It is recommended that you use
`checkbounds` to confirm the indices are safe for loops.
Also be aware when writing generic code that faces may be of more than
3 vertices.
"""
@generated function Base.getindex{T,N,FD,FT,Offset}(a::Array{T,N},
f::Face{FD, FT, Offset})
v = Expr(:tuple)
for i = 1:FD
push!(v.args, Expr(:call, Base.unsafe_getindex, :a, :(f[$i]-Offset)))
end
Expr(:(::), v, :(NTuple{FD,T}))
end

function setindex!{T,N,FD,FT,Offset}(a::Array{T,N}, b::Array{T,N}, i::Face{FD, FT, Offset})
a[[(map(Int,i)-Offset)...]] = b
end
Expand Down
6 changes: 6 additions & 0 deletions test/faces.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
context("faces") do
a = [1,2,3,4]
@fact a[Face{3,Int,0}(1,2,3)] --> (1,2,3)
@fact a[Face{3,Int,-1}(0,1,2)] --> (1,2,3)
@fact a[Face{3,Int,1}(2,3,4)] --> (1,2,3)
end
19 changes: 19 additions & 0 deletions test/meshtypes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,23 @@ context("Slice") do
@fact length(s2) --> length(exp2)
end

context("checkbounds") do
m1 = HomogenousMesh([Point{3,Float64}(0.0,0.0,10.0),
Point{3,Float64}(0.0,10.0,10.0),
Point{3,Float64}(0.0,0.0,0.0)],
[Face{3,Int,0}(1,2,3)])
@fact checkbounds(m1) --> true
m2 = HomogenousMesh([Point{3,Float64}(0.0,0.0,10.0),
Point{3,Float64}(0.0,10.0,10.0),
Point{3,Float64}(0.0,0.0,0.0)],
[Face{3,Int,-1}(1,2,3)])
@fact checkbounds(m2) --> false
# empty case
m3 = HomogenousMesh([Point{3,Float64}(0.0,0.0,10.0),
Point{3,Float64}(0.0,10.0,10.0),
Point{3,Float64}(0.0,0.0,0.0)],
Face{3,Int,-1}[])
@fact checkbounds(m3) --> true
end

end
1 change: 1 addition & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ typealias Vec3f0 Vec{3, Float32}

facts("GeometryTypes") do
include("hyperrectangles.jl")
include("faces.jl")
include("meshtypes.jl")
include("distancefields.jl")
include("primitives.jl")
Expand Down

0 comments on commit 762f23a

Please sign in to comment.