File: vecelement.jl

package info (click to toggle)
julia 1.0.3%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 49,452 kB
  • sloc: lisp: 236,453; ansic: 55,579; cpp: 25,603; makefile: 1,685; pascal: 1,130; sh: 956; asm: 86; xml: 76
file content (121 lines) | stat: -rw-r--r-- 3,405 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
# This file is a part of Julia. License is MIT: https://julialang.org/license

make_value(::Type{T}, i::Integer) where {T<:Integer} = 3*i%T
make_value(::Type{T},i::Integer) where {T<:AbstractFloat} = T(3*i)

Vec{N,T} = NTuple{N,Base.VecElement{T}}

# Crash report for #15244 motivated this test.
@generated function thrice_iota(::Type{Vec{N,T}}) where {N,T}
    :(tuple($([:(Base.VecElement(make_value($T,$i))) for i in 1:N]...)))
end

function call_iota(n::Integer,t::DataType)
    x = thrice_iota(Vec{n,t})
    @test x[1].value === make_value(t,1)
    @test x[n].value === make_value(t,n)
end

# Try various tuple lengths and element types
for i=1:20
    for t in [Bool, Int8, Int16, Int32, Int64, Float32, Float64]
        call_iota(i,t)
    end
end

# Try various large tuple lengths and element types #20961
for i in (34, 36, 48, 64, 72, 80, 96)
    for t in [Bool, Int8, Int16, Int32, Int64, Float32, Float64]
        call_iota(i,t)
    end
end

# Another crash report for #15244 motivated this test.
struct Bunch{N,T}
    elts::NTuple{N,Base.VecElement{T}}
end

unpeel(x) = x.elts[1].value
@test unpeel(Bunch{2,Float64}((Base.VecElement(5.0),
                               Base.VecElement(4.0)))) === 5.0

rewrap(x) = VecElement(x.elts[1].value + 0)
let b = Bunch((VecElement(1.0), VecElement(2.0)))
    @test rewrap(b) === VecElement(1.0)
end

struct Herd{N,T}
    elts::NTuple{N,Base.VecElement{T}}
    Herd{N,T}(elts::NTuple{N,T}) where {N,T} = new(ntuple(i->Base.VecElement{T}(elts[i]), N))
end

function check(x::Herd{N,T}) where {N,T}
    for i=1:N
        @test x.elts[i].value === N*N+i-1
    end
end

check(Herd{1,Int}((1,)))
check(Herd{2,Int}((4,5)))
check(Herd{4,Int}((16,17,18,19)))

struct Gr{N, T}
    u::T
    v::Bunch{N,T}
    w::T
end

let a = Vector{Gr{2,Float64}}(undef, 2)
    a[2] = Gr(1.0, Bunch((VecElement(2.0), VecElement(3.0))), 4.0)
    a[1] = Gr(5.0, Bunch((VecElement(6.0), VecElement(7.0))), 8.0)
    @test a[2] == Gr(1.0, Bunch((VecElement(2.0), VecElement(3.0))), 4.0)
end

@test isa(VecElement((1,2)), VecElement{Tuple{Int,Int}})

# The following test mimic SIMD.jl
const _llvmtypes = Dict{DataType, String}(
    Float64 => "double",
    Float32 => "float",
    Int32 => "i32",
    Int64 => "i64"
)

@generated function vecadd(x::Vec{N, T}, y::Vec{N, T}) where {N, T}
    llvmT = _llvmtypes[T]
    func = T <: AbstractFloat ? "fadd" : "add"
    exp = """
    %3 = $(func) <$(N) x $(llvmT)> %0, %1
    ret <$(N) x $(llvmT)> %3
    """
    return quote
        Base.@_inline_meta
        Core.getfield(Base, :llvmcall)($exp, Vec{$N, $T}, Tuple{Vec{$N, $T}, Vec{$N, $T}}, x, y)
    end
end

function f20961(x::Vector{Vec{N, T}}, y::Vector{Vec{N, T}}) where{N, T}
    @inbounds begin
        a = x[1]
        b = y[1]
        return vecadd(a, b)
    end
end

# Test various SIMD Vectors with known good sizes
for T in (Float64, Float32, Int64, Int32)
    for N in 1:36
        # For some vectortypes Julia emits llvm arrays instead of vectors
        if N %  7 == 0 || N % 11 == 0 || N % 13 == 0 || N % 15 == 0 ||
           N % 19 == 0 || N % 23 == 0 || N % 25 == 0 || N % 27 == 0 ||
           N % 29 == 0 || N % 31 == 0
            continue
        end
        a = ntuple(i->VecElement(T(i)), N)
        result = ntuple(i-> VecElement(T(i+i)), N)
        b = vecadd(a, a)
        @test b == result
        b = f20961([a], [a])
        @test b == result
    end
end