Skip to content

Commit

Permalink
Merge pull request #36 from KristofferC/kc/no_dense_vec
Browse files Browse the repository at this point in the history
remove DenseVector subtyping
  • Loading branch information
eschnett authored Oct 24, 2018
2 parents 49fd8b0 + 2cf355a commit 4e11208
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 44 deletions.
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ By exposing SIMD vector types and corresponding operations, the programmer can e
Here is a simple example for a manually vectorized code that adds two arrays:
```Julia
using SIMD
function vadd!{N,T}(xs::Vector{T}, ys::Vector{T}, ::Type{Vec{N,T}})
function vadd!(xs::Vector{T}, ys::Vector{T}, ::Type{Vec{N,T}}) where {N, T}
@assert length(ys) == length(xs)
@assert length(xs) % N == 0
@inbounds for i in 1:N:length(xs)
Expand Down Expand Up @@ -79,7 +79,7 @@ sum(v)
When using explicit SIMD vectorization, it is convenient to allocate arrays still as arrays of scalars, not as arrays of vectors. The `vload` and `vstore` functions allow reading vectors from and writing vectors into arrays, accessing several contiguous array elements.

```Julia
arr = Vector{Float64}(100)
arr = Vector{Float64}(undef, 100)
...
xs = vload(Vec{4,Float64}, arr, i)
...
Expand All @@ -97,7 +97,7 @@ a = Vec{4, Int32}((1,2,3,4))
b = Vec{4, Int32}((5,6,7,8))
mask = (2,3,4,5)
shufflevector(a, b, Val{mask})
Int323,4,5,6
<4 x Int32>[3, 4, 5, 6]
```
The mask specifies vector elements counted across `a` and `b`,
starting at 0 to follow the LLVM convention. If you don't care about
Expand All @@ -112,7 +112,7 @@ There is also a one operand version of the function:
a = Vec{4, Int32}((1,2,3,4))
mask = (0,3,1,2)
shufflevector(a, Val{mask})
Int321,4,2,3
<4 x Int32>[1, 4, 2, 3]
```

## Representing SIMD vector types in Julia
Expand Down Expand Up @@ -152,7 +152,7 @@ code would break as a result.

We thus define our own SIMD vector type `Vec{N,T}`:
```Julia
immutable Vec{N,T} <: DenseArray{N,1}
elts::NTuple{N,T}
struct Vec{N,T}
elts::NTuple{N,VecElement{T}}
end
```
53 changes: 21 additions & 32 deletions src/SIMD.jl
Original file line number Diff line number Diff line change
Expand Up @@ -62,47 +62,30 @@ const ScalarTypes = Union{IntegerTypes, FloatingTypes}
const VE = Base.VecElement

export Vec
struct Vec{N,T<:ScalarTypes} <: DenseArray{T,1} # <: Number
struct Vec{N,T<:ScalarTypes} # <: Number
elts::NTuple{N,VE{T}}
@inline Vec{N,T}(elts::NTuple{N, VE{T}}) where {N,T} = new{N,T}(elts)
end

function Base.show(io::IO, v::Vec{N,T}) where {N,T}
print(io, T, "")
for i in 1:N
i>1 && print(io, ", ")
print(io, v.elts[i].value)
end
print(io, "")
end

# Base.print_matrix wants to access a second dimension that doesn't exist for
# Vec. (In Julia, every array can be accessed as N-dimensional array, for
# arbitrary N.) Instead of implementing this, output our Vec the usual way.
function Base.print_matrix(io::IO, X::Vec,
pre::AbstractString = " ", # pre-matrix string
sep::AbstractString = " ", # separator between elements
post::AbstractString = "", # post-matrix string
hdots::AbstractString = " \u2026 ",
vdots::AbstractString = "\u22ee",
ddots::AbstractString = " \u22f1 ",
hmod::Integer = 5, vmod::Integer = 5)
print(io, X)
print(io, "<$N x $T>[")
join(io, [x.value for x in v.elts], ", ")
print(io, "]")
end

# Type properties

# eltype and ndims are provided by DenseArray
# Base.eltype{N,T}(::Type{Vec{N,T}}) = T
# Base.ndims{N,T}(::Type{Vec{N,T}}) = 1
Base.eltype(::Type{Vec{N,T}}) where {N,T} = T
Base.ndims( ::Type{Vec{N,T}}) where {N,T} = 1
Base.length(::Type{Vec{N,T}}) where {N,T} = N
Base.size(::Type{Vec{N,T}}) where {N,T} = (N,)
Base.size( ::Type{Vec{N,T}}) where {N,T} = (N,)
# TODO: This doesn't follow Base, e.g. `size([], 3) == 1`
Base.size(::Type{Vec{N,T}}, n::Integer) where {N,T} = (N,)[n]
# Base.eltype{N,T}(::Vec{N,T}) = T
# Base.ndims{N,T}(::Vec{N,T}) = 1
Base.length(::Vec{N,T}) where {N,T} = N
Base.size(::Vec{N,T}) where {N,T} = (N,)
Base.size(::Vec{N,T}, n::Integer) where {N,T} = (N,)[n]

Base.eltype(V::Vec) = eltype(typeof(V))
Base.ndims( V::Vec) = ndims(typeof(V))
Base.length(V::Vec) = length(typeof(V))
Base.size( V::Vec) = size(typeof(V))
Base.size( V::Vec, n::Integer) = size(typeof(V), n)

# Type conversion

Expand All @@ -124,7 +107,13 @@ Vec(xs::NTuple{N,T}) where {N,T<:ScalarTypes} = Vec{N,T}(xs)

# Convert between vectors
@inline Base.convert(::Type{Vec{N,T}}, v::Vec{N,T}) where {N,T} = v
@inline Base.convert(::Type{Vec{N,R}}, v::Vec{N,T}) where {N,R,T} = Vec{N,R}(Tuple(v))

@inline Base.convert(::Type{Vec{N,R}}, v::Vec{N}) where {N,R} =
Vec{N,R}(NTuple{N, R}(v))

@inline Tuple(v::Vec{N}) where {N} = ntuple(i -> v.elts[i].value, Val(N))
@inline NTuple{N, T}(v::Vec{N}) where{N, T} = ntuple(i -> convert(T, v.elts[i].value), Val(N))

@generated function Base. %(v::Vec{N,T}, ::Type{Vec{N,R}}) where {N,R,T}
quote
$(Expr(:meta, :inline))
Expand Down
12 changes: 6 additions & 6 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,17 @@ using Test, InteractiveUtils
global const v8i32 = ntuple(i->Int32(ifelse(isodd(i), i, -i)), L8)
global const v4f64 = ntuple(i->Float64(ifelse(isodd(i), i, -i)), L4)

@test string(V8I32(v8i32)) == "Int32" * string(v8i32)[2:end-1] * ""
@test string(V4F64(v4f64)) == "Float64" * string(v4f64)[2:end-1] * ""
@test string(V8I32(v8i32)) == "<8 x Int32>[" * string(v8i32)[2:end-1] * "]"
@test string(V4F64(v4f64)) == "<4 x Float64>[" * string(v4f64)[2:end-1] * "]"

@test convert(V8I32, V8I32(v8i32)) === V8I32(v8i32)
@test convert(Vec{L8,Int64}, V8I32(v8i32)) ===
Vec{L8, Int64}(convert(NTuple{L8,Int64}, v8i32))

@test NTuple{L8,Int32}(V8I32(v8i32)) === v8i32
@test NTuple{L4,Float64}(V4F64(v4f64)) === v4f64
@test Tuple(V8I32(v8i32)) === v8i32
@test Tuple(V4F64(v4f64)) === v4f64
@test NTuple{L8,Int32}(V8I32(v8i32)) === Tuple(v8i32)
@test NTuple{L4,Float64}(V4F64(v4f64)) === Tuple(v4f64)
@test Tuple(V8I32(v8i32)) === Tuple(v8i32)
@test Tuple(V4F64(v4f64)) === Tuple(v4f64)
end

@testset "Element-wise access" begin
Expand Down

0 comments on commit 4e11208

Please sign in to comment.