Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add some more functions and improve broadcasting support #69

Merged
merged 4 commits into from
Jun 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/AppleAccelerate.jl
Original file line number Diff line number Diff line change
Expand Up @@ -92,9 +92,9 @@ function __init__()
end

if Sys.isapple()
include("Util.jl")
include("Array.jl")
include("DSP.jl")
include("Util.jl")
end

end # module
136 changes: 135 additions & 1 deletion src/Array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,9 @@
Base.copy(bc::Base.Broadcast.Broadcasted{Style, Axes, typeof($f), Tuple{Array{$T, N}}}) where {Style, Axes, N} = ($f)(bc.args...)
Base.copyto!(dest::Array{$T, N}, bc::Base.Broadcast.Broadcasted{Style, Axes, typeof($f), Tuple{Array{$T, N}}}) where {Style, Axes, N} = ($f!)(dest, bc.args...)
end
if T == Float32
@eval Base.broadcasted(::typeof($f), arg::Union{Array{F,N},Base.Broadcast.Broadcasted}) where {N,F<:Union{Float32,Float64}} = ($f)(maybecopy(arg))
end
end
for (f, fa) in (twoarg_funcs...,(:pow,:pow))
f! = Symbol("$(f)!")
Expand All @@ -124,14 +127,19 @@
Base.copy(bc::Base.Broadcast.Broadcasted{Style, Axes, typeof($f), Tuple{Array{$T, N},Array{$T,N}}}) where {Style, Axes, N} = ($f)(bc.args...)
Base.copyto!(dest::Array{$T, N}, bc::Base.Broadcast.Broadcasted{Style, Axes, typeof($f), Tuple{Array{$T,N},Array{$T,N}}}) where {Style, Axes, N} = ($f!)(dest, bc.args...)
end
if T == Float32
@eval Base.broadcasted(::typeof($f), arg1::Union{Array{F, N},Base.Broadcast.Broadcasted}, arg2::Union{Array{F, N},Base.Broadcast.Broadcasted}) where {N,F<:Union{Float32,Float64}} = ($f)(maybecopy(arg1), maybecopy(arg2))
end
end
end

# Functions over single vectors that return scalars/tuples
for (T, suff) in ((Float32, ""), (Float64, "D"))

for (f, fa) in ((:maximum, :maxv), (:minimum, :minv), (:mean, :meanv),
(:meansqr, :measqv), (:meanmag, :meamgv), (:sum, :sve))
(:meanmag, :meamgv), (:meansqr, :measqv), (:meanssqr, :mvessq),
(:sum, :sve), (:summag, :svemg), (:sumsqr, :svesq),
(:sumssqr, :svs))
@eval begin
function ($f)(X::Vector{$T})
val = Ref{$T}(0.0)
Expand Down Expand Up @@ -192,7 +200,133 @@
return result
end
end

@eval begin
# Broadcasting override such that f.(X) turns into f(X)
Base.copy(bc::Base.Broadcast.Broadcasted{Style, Axes, typeof($f), Tuple{Array{$T, N},Array{$T,N}}}) where {Style, Axes, N} = ($f)(bc.args...)
Base.copyto!(dest::Array{$T, N}, bc::Base.Broadcast.Broadcasted{Style, Axes, typeof($f), Tuple{Array{$T,N},Array{$T,N}}}) where {Style, Axes, N} = ($f!)(dest, bc.args...)

Check warning on line 207 in src/Array.jl

View check run for this annotation

Codecov / codecov/patch

src/Array.jl#L206-L207

Added lines #L206 - L207 were not covered by tests
Base.broadcasted(::typeof($f), arg1::Union{Array{$T, N},Base.Broadcast.Broadcasted}, arg2::Union{Array{$T, N},Base.Broadcast.Broadcasted}) where {N} = ($f)(maybecopy(arg1), maybecopy(arg2))
end
end
end

# Element-wise operations over a vector and a scalar
for (T, suff) in ((Float32, ""), (Float64, "D"))

for (f, name) in ((:vsadd, "addition"), (:vsdiv, "division"), (:vsmul, "multiplication"))
f! = Symbol("$(f)!")

@eval begin
@doc """

Check warning on line 220 in src/Array.jl

View check run for this annotation

Codecov / codecov/patch

src/Array.jl#L220

Added line #L220 was not covered by tests
`$($f!)(result::Vector{$($T)}, X::Vector{$($T)}, c::$($T))`

Implements vector-scalar **$($name)** over **Vector{$($T)}** and $($T) and overwrites
the result vector with computed value. *Returns:* **Vector{$($T)}** `result`
""" ->
function ($f!)(result::Vector{$T}, X::Vector{$T}, c::$T)
ccall(($(string("vDSP_", f, suff), libacc)), Cvoid,
(Ptr{$T}, Int64, Ptr{$T}, Ptr{$T}, Int64, UInt64),
X, 1, Ref(c), result, 1, length(result))
return result
end
end

@eval begin
@doc """

Check warning on line 235 in src/Array.jl

View check run for this annotation

Codecov / codecov/patch

src/Array.jl#L235

Added line #L235 was not covered by tests
`$($f)(X::Vector{$($T)}, c::$($T))`

Implements vector-scalar **$($name)** over **Vector{$($T)}** and $($T). Allocates
memory to store result. *Returns:* **Vector{$($T)}**
""" ->
function ($f)(X::Vector{$T}, c::$T)
result = similar(X)
($f!)(result, X, c)
return result
end
end
end
f = :vssub
f! = Symbol("$(f)!")

@eval begin
@doc """

Check warning on line 252 in src/Array.jl

View check run for this annotation

Codecov / codecov/patch

src/Array.jl#L252

Added line #L252 was not covered by tests
`$($f!)(result::Vector{$($T)}, X::Vector{$($T)}, c::$($T))`

Implements vector-scalar **subtraction** over **Vector{$($T)}** and $($T) and overwrites
the result vector with computed value. *Returns:* **Vector{$($T)}** `result`
""" ->
function ($f!)(result::Vector{$T}, X::Vector{$T}, c::$T)
ccall(($(string("vDSP_vsadd", suff), libacc)), Cvoid,
(Ptr{$T}, Int64, Ptr{$T}, Ptr{$T}, Int64, UInt64),
X, 1, Ref(-c), result, 1, length(result))
return result
end
end

@eval begin
@doc """

Check warning on line 267 in src/Array.jl

View check run for this annotation

Codecov / codecov/patch

src/Array.jl#L267

Added line #L267 was not covered by tests
`$($f)(X::Vector{$($T)}, c::$($T))`

Implements vector-scalar **subtraction** over **Vector{$($T)}** and $($T). Allocates
memory to store result. *Returns:* **Vector{$($T)}**
""" ->
function ($f)(X::Vector{$T}, c::$T)
result = similar(X)
($f!)(result, X, c)
return result
end
end

f = :svsub
f! = Symbol("$(f)!")

@eval begin
@doc """

Check warning on line 284 in src/Array.jl

View check run for this annotation

Codecov / codecov/patch

src/Array.jl#L284

Added line #L284 was not covered by tests
`$($f!)(result::Vector{$($T)}, X::Vector{$($T)}, c::$($T))`

Implements vector-scalar **subtraction** over $($T) and **Vector{$($T)}** and overwrites
the result vector with computed value. *Returns:* **Vector{$($T)}** `result`
""" ->
function ($f!)(result::Vector{$T}, X::Vector{$T}, c::$T)
ccall(($(string("vDSP_vsadd", suff), libacc)), Cvoid,
(Ptr{$T}, Int64, Ptr{$T}, Ptr{$T}, Int64, UInt64),
-X, 1, Ref(c), result, 1, length(result))
return result
end
end

@eval begin
@doc """

Check warning on line 299 in src/Array.jl

View check run for this annotation

Codecov / codecov/patch

src/Array.jl#L299

Added line #L299 was not covered by tests
`$($f)(X::Vector{$($T), c::$($T)})`

Implements vector-scalar **subtraction** over $($T) and **Vector{$($T)}**. Allocates
memory to store result. *Returns:* **Vector{$($T)}**
""" ->
function ($f)(X::Vector{$T}, c::$T)
result = similar(X)
($f!)(result, X, c)
return result
end
end

for f in (:vsadd, :vssub, :vsdiv, :vsmul)
f! = Symbol("$(f)!")
@eval begin
# Broadcasting override such that f.(X) turns into f(X)
Base.copy(bc::Base.Broadcast.Broadcasted{Style, Axes, typeof($f), Tuple{Array{$T, N},$T}}) where {Style, Axes, N} = ($f)(bc.args...)
Base.copyto!(dest::Array{$T, N}, bc::Base.Broadcast.Broadcasted{Style, Axes, typeof($f), Tuple{Array{$T,N},$T}}) where {Style, Axes, N} = ($f!)(dest, bc.args...)

Check warning on line 317 in src/Array.jl

View check run for this annotation

Codecov / codecov/patch

src/Array.jl#L316-L317

Added lines #L316 - L317 were not covered by tests
Base.broadcasted(::typeof($f), arg1::Union{Array{$T, N},Base.Broadcast.Broadcasted}, arg2::$T) where {N} = ($f)(maybecopy(arg1), arg2)
end
end

f = :svsub
f! = Symbol("$(f)!")

@eval begin
# Broadcasting override such that f.(X) turns into f(X)
Base.copy(bc::Base.Broadcast.Broadcasted{Style, Axes, typeof($f), Tuple{Array{$T, N}, $T}}) where {Style, Axes, N} = ($f)(bc.args...)
Base.copyto!(dest::Array{$T, N}, bc::Base.Broadcast.Broadcasted{Style, Axes, typeof($f), Tuple{Array{$T,N}, $T}}) where {Style, Axes, N} = ($f!)(dest, bc.args...)

Check warning on line 328 in src/Array.jl

View check run for this annotation

Codecov / codecov/patch

src/Array.jl#L327-L328

Added lines #L327 - L328 were not covered by tests
Base.broadcasted(::typeof($f), arg1::Union{Array{$T, N},Base.Broadcast.Broadcasted}, arg2::$T) where {N} = ($f)(maybecopy(arg1), arg2)
end
end

22 changes: 21 additions & 1 deletion src/Util.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,13 @@

tupletypelength(a)=length(a.parameters)

@inline maybecopy(x::T) where {T <: Base.Broadcast.Broadcasted} = copy(x)
@inline maybecopy(x::T) where {T <: Array} = x

const OPS = Dict{Symbol,Tuple{Symbol, Symbol, Symbol}}(:+ => (:vadd, :vsadd, :vsadd),
:- => (:vsub, :vssub, :svsub),
:* => (:vadd, :vsmul, :vsmul),
:/ => (:vadd, :vsdiv, :vsdiv),)

macro replaceBase(fs...)
b = Expr(:block)
Expand All @@ -28,16 +35,29 @@
e = quote
(Base.$f)(X::Array{T}) where {T <: Union{Float64,Float32}} = ($fa)(X)
(Base.$f)(X::Union{Float64,Float32}) = ($fa)([X])[1]
Base.broadcasted(::typeof(Base.$f), arg::Union{Array{F,N},Base.Broadcast.Broadcasted}) where {N,F<:Union{Float32,Float64}} = ($fa)(maybecopy(arg))

Check warning on line 38 in src/Util.jl

View check run for this annotation

Codecov / codecov/patch

src/Util.jl#L38

Added line #L38 was not covered by tests
end
arg_consumed = true
end
if fa in (:copysign,:atan,:pow,:rem,:div_float, :vadd, :vsub, :vmul)
if fa in (:copysign,:atan,:pow,:rem)
e = quote
(Base.$f)(X::Array{T},Y::Array{T}) where {T <: Union{Float32,Float64}} = ($fa)(X,Y)
(Base.$f)(X::T,Y::T) where {T <: Union{Float32,Float64}} = ($fa)([X],[Y])[1]
Base.broadcasted(::typeof(Base.$f), arg1::Union{Array{F, N},Base.Broadcast.Broadcasted}, arg2::Union{Array{F, N},Base.Broadcast.Broadcasted}) where {N,F<:Union{Float32,Float64}} = ($fa)(maybecopy(arg1), maybecopy(arg2))

Check warning on line 46 in src/Util.jl

View check run for this annotation

Codecov / codecov/patch

src/Util.jl#L46

Added line #L46 was not covered by tests
end
arg_consumed = true
end
if f in (:+,:-,:*,:/)
e = quote
(Base.$f)(X::Array{T},Y::Array{T}) where {T <: Union{Float32,Float64}} = ($(OPS[f][1]))(X,Y)
(Base.$f)(X::T,Y::T) where {T <: Union{Float32,Float64}} = ($(OPS[f][1]))([X],[Y])[1]
Base.broadcasted(::typeof(Base.$f), arg1::Union{Array{F, N},Base.Broadcast.Broadcasted}, arg2::Union{Array{F, N},Base.Broadcast.Broadcasted}) where {N,F<:Union{Float32,Float64}} = ($(OPS[f][1]))(maybecopy(arg1), maybecopy(arg2))

Check warning on line 54 in src/Util.jl

View check run for this annotation

Codecov / codecov/patch

src/Util.jl#L52-L54

Added lines #L52 - L54 were not covered by tests

Base.broadcasted(::typeof(Base.$f), arg1::Union{Array{T, N},Base.Broadcast.Broadcasted}, arg2::T) where {N, T <: Union{Float32,Float64}} = ($(OPS[f][2]))(maybecopy(arg1), arg2)
Base.broadcasted(::typeof(Base.$f), arg1::T, arg2::Union{Array{T, N},Base.Broadcast.Broadcasted}) where {N, T <: Union{Float32,Float64}} = ($(OPS[f][3]))(maybecopy(arg2), arg1)

Check warning on line 57 in src/Util.jl

View check run for this annotation

Codecov / codecov/patch

src/Util.jl#L56-L57

Added lines #L56 - L57 were not covered by tests
end
arg_consumed = true
end
if !arg_consumed
error("Function $f not defined by AppleAccelerate.jl")
end
Expand Down
73 changes: 69 additions & 4 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,62 @@ end
Random.seed!(7)
N = 1_000

@testset "AppleAccelerate.jl" begin
for T in (Float32, Float64)
@testset "Element-wise Operators::$T" begin
X::Vector{T} = randn(N)
Y::Vector{T} = randn(N)
Z::Vector{T} = similar(X)
# Vector-vector
@test (X .+ Y) ≈ AppleAccelerate.vadd(X, Y)
@test (X .- Y) ≈ AppleAccelerate.vsub(X, Y)
@test (X .* Y) ≈ AppleAccelerate.vmul(X, Y)
@test (X ./ Y) ≈ AppleAccelerate.vdiv(X, Y)

# Vector-vector non-allocating
AppleAccelerate.vadd!(Z, X, Y)
@test (X .+ Y) ≈ Z
AppleAccelerate.vsub!(Z, X, Y)
@test (X .- Y) ≈ Z
AppleAccelerate.vmul!(Z, X, Y)
@test (X .* Y) ≈ Z
AppleAccelerate.vdiv!(Z, X, Y)
@test (X ./ Y) ≈ Z

# Vector-vector broadcasting
@test (X .+ Y) ≈ AppleAccelerate.vadd.(X, Y)
@test (X .- Y) ≈ AppleAccelerate.vsub.(X, Y)
@test (X .* Y) ≈ AppleAccelerate.vmul.(X, Y)
@test (X ./ Y) ≈ AppleAccelerate.vdiv.(X, Y)

#Vector-scalar
c::T = randn()
@test (X .+ c) ≈ AppleAccelerate.vsadd.(X, c)
@test (X .- c) ≈ AppleAccelerate.vssub.(X, c)
@test (c .- X) ≈ AppleAccelerate.svsub.(X, c)
@test (X .* c) ≈ AppleAccelerate.vsmul.(X, c)
@test (X ./ c) ≈ AppleAccelerate.vsdiv.(X, c)

#Vector-scalar non-allocating
AppleAccelerate.vsadd!(Y, X, c)
@test (X .+ c) ≈ Y
AppleAccelerate.vssub!(Y, X, c)
@test (X .- c) ≈ Y
AppleAccelerate.svsub!(Y, X, c)
@test (c .- X) ≈ Y
AppleAccelerate.vsmul!(Y, X, c)
@test (X .* c) ≈ Y
AppleAccelerate.vsdiv!(Y, X, c)
@test (X ./ c) ≈ Y

#Vector-scalar broadcasting
@test (X .+ c) ≈ AppleAccelerate.vsadd.(X, c)
@test (X .- c) ≈ AppleAccelerate.vssub.(X, c)
@test (c .- X) ≈ AppleAccelerate.svsub.(X, c)
@test (X .* c) ≈ AppleAccelerate.vsmul.(X, c)
@test (X ./ c) ≈ AppleAccelerate.vsdiv.(X, c)

@test (X .+ Y .+ Y) ≈ AppleAccelerate.vadd.(X, Y .+ Y)
end
end

Expand Down Expand Up @@ -198,12 +246,28 @@ for T in (Float32, Float64)
@test fa(X)[2] ≈ fb(X)[2]
end

@testset "Testing meanmag::$T" begin
@test AppleAccelerate.meanmag(X) ≈ mean(abs, X)
end

@testset "Testing meansqr::$T" begin
@test AppleAccelerate.meansqr(X) ≈ mean(X .*X)
@test AppleAccelerate.meansqr(X) ≈ mean(X .* X)
end

@testset "Testing meanmag::$T" begin
@test AppleAccelerate.meanmag(X) ≈ mean(abs.(X))
@testset "Testing meanssqr::$T" begin
@test AppleAccelerate.meanssqr(X) ≈ mean(X .* abs.(X))
end

@testset "Testing summag::$T" begin
@test AppleAccelerate.summag(X) ≈ sum(abs, X)
end

@testset "Testing sumsqr::$T" begin
@test AppleAccelerate.sumsqr(X) ≈ sum(abs2, X)
end

@testset "Testing sumssqr::$T" begin
@test AppleAccelerate.sumssqr(X) ≈ sum(X .* abs.(X))
end

end
Expand Down Expand Up @@ -270,6 +334,7 @@ Y::Array{T} = abs.(randn(N))
@test X ./ Y == AppleAccelerate.div_float(X, Y)
end
=#
end

if AppleAccelerate.get_macos_version() < v"13.3"
@info("AppleAccelerate.jl needs macOS >= 13.3 for BLAS forwarding. Not testing forwarding capabilities.")
Expand Down Expand Up @@ -338,6 +403,6 @@ end
end

run(`$(Base.julia_cmd()) --project=$(Base.active_project()) $(dir)/runtests.jl LinearAlgebra/blas LinearAlgebra/lapack`)
end;
end;
end

Loading