Skip to content

Commit 0af280a

Browse files
iolaszloKristofferC
authored andcommitted
Add hpmv! to BLAS in stdlib/LinearAlgebra (#34211)
1 parent d0f637c commit 0af280a

File tree

3 files changed

+119
-0
lines changed

3 files changed

+119
-0
lines changed

NEWS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ Standard library changes
3131

3232
#### LinearAlgebra
3333

34+
* The BLAS submodule now supports the level-2 BLAS subroutine `hpmv!` ([#34211]).
3435

3536
#### Markdown
3637

stdlib/LinearAlgebra/src/blas.jl

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export
2828
gemv,
2929
hemv!,
3030
hemv,
31+
hpmv!,
3132
sbmv!,
3233
sbmv,
3334
symv!,
@@ -823,6 +824,82 @@ Only the [`ul`](@ref stdlib-blas-uplo) triangle of `A` is used.
823824
"""
824825
hemv(ul, A, x)
825826

827+
### hpmv!, (HP) Hermitian packed matrix-vector operation defined as y := alpha*A*x + beta*y.
828+
for (fname, elty) in ((:zhpmv_, :ComplexF64),
829+
(:chpmv_, :ComplexF32))
830+
@eval begin
831+
# SUBROUTINE ZHPMV(UPLO,N,ALPHA,AP,X,INCX,BETA,Y,INCY)
832+
# Y <- ALPHA*AP*X + BETA*Y
833+
# * .. Scalar Arguments ..
834+
# DOUBLE PRECISION ALPHA,BETA
835+
# INTEGER INCX,INCY,N
836+
# CHARACTER UPLO
837+
# * .. Array Arguments ..
838+
# DOUBLE PRECISION A(N,N),X(N),Y(N)
839+
function hpmv!(uplo::AbstractChar,
840+
n::BlasInt,
841+
α::$elty,
842+
AP::Union{Ptr{$elty}, AbstractArray{$elty}},
843+
x::Union{Ptr{$elty}, AbstractArray{$elty}},
844+
incx::Integer,
845+
β::$elty,
846+
y::Union{Ptr{$elty}, AbstractArray{$elty}},
847+
incy::Integer)
848+
849+
ccall((@blasfunc($fname), libblas), Cvoid,
850+
(Ref{UInt8}, # uplo,
851+
Ref{BlasInt}, # n,
852+
Ref{$elty}, # α,
853+
Ptr{$elty}, # AP,
854+
Ptr{$elty}, # x,
855+
Ref{BlasInt}, # incx,
856+
Ref{$elty}, # β,
857+
Ptr{$elty}, # y, output
858+
Ref{BlasInt}), # incy
859+
uplo,
860+
n,
861+
α,
862+
AP,
863+
x,
864+
incx,
865+
β,
866+
y,
867+
incy)
868+
end
869+
end
870+
end
871+
872+
function hpmv!(uplo::AbstractChar,
873+
α::Number, AP::Union{DenseArray{T}, AbstractVector{T}}, x::Union{DenseArray{T}, AbstractVector{T}},
874+
β::Number, y::Union{DenseArray{T}, AbstractVector{T}}) where {T <: BlasComplex}
875+
require_one_based_indexing(AP, x, y)
876+
N = length(x)
877+
if N != length(y)
878+
throw(DimensionMismatch("x has length $(N), but y has length $(length(y))"))
879+
end
880+
if length(AP) < Int64(N*(N+1)/2)
881+
throw(DimensionMismatch("Packed Hermitian matrix A has size smaller than length(x) = $(N)."))
882+
end
883+
GC.@preserve x y AP hpmv!(uplo, N, convert(T, α), AP, pointer(x), BlasInt(stride(x, 1)), convert(T, β), pointer(y), BlasInt(stride(y, 1)))
884+
y
885+
end
886+
887+
"""
888+
hpmv!(uplo, α, AP, x, β, y)
889+
890+
Update vector `y` as `α*AP*x + β*y` where `AP` is a packed Hermitian matrix.
891+
The storage layout for `AP` is described in the reference BLAS module, level-2 BLAS at
892+
<http://www.netlib.org/lapack/explore-html/>.
893+
894+
The scalar inputs `α` and `β` shall be numbers.
895+
896+
The array inputs `x`, `y` and `AP` must be complex one-dimensional julia arrays of the
897+
same type that is either `ComplexF32` or `ComplexF64`.
898+
899+
Return the updated `y`.
900+
"""
901+
hpmv!
902+
826903
### sbmv, (SB) symmetric banded matrix-vector multiplication
827904
for (fname, elty) in ((:dsbmv_,:Float64),
828905
(:ssbmv_,:Float32))

stdlib/LinearAlgebra/test/blas.jl

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ using LinearAlgebra: BlasReal, BlasComplex
88
Random.seed!(100)
99
## BLAS tests - testing the interface code to BLAS routines
1010
@testset for elty in [Float32, Float64, ComplexF32, ComplexF64]
11+
1112
@testset "syr2k!" begin
1213
U = randn(5,2)
1314
V = randn(5,2)
@@ -200,6 +201,46 @@ Random.seed!(100)
200201
@test_throws DimensionMismatch BLAS.trmm('R','U','N','N',one(elty),triu(Cnn),Cnm)
201202
end
202203

204+
# hpmv!
205+
if elty in (ComplexF32, ComplexF64)
206+
@testset "hpmv!" begin
207+
# Both matrix dimensions n coincide, as we have Hermitian matrices.
208+
# Define the inputs and outputs of hpmv!, y = α*A*x+β*y
209+
α = rand(elty)
210+
M = rand(elty, n, n)
211+
A = (M+M')/elty(2.0)
212+
x = rand(elty, n)
213+
β = rand(elty)
214+
y = rand(elty, n)
215+
216+
y_result_julia = α*A*x+β*y
217+
218+
# Create lower triangular packing of A
219+
AP = typeof(A[1,1])[]
220+
for j in 1:n
221+
for i in j:n
222+
push!(AP, A[i,j])
223+
end
224+
end
225+
226+
y_result_blas_lower = copy(y)
227+
BLAS.hpmv!('L', α, AP, x, β, y_result_blas_lower)
228+
@test y_result_juliay_result_blas_lower
229+
230+
# Create upper triangular packing of A
231+
AP = typeof(A[1,1])[]
232+
for j in 1:n
233+
for i in 1:j
234+
push!(AP, A[i,j])
235+
end
236+
end
237+
238+
y_result_blas_upper = copy(y)
239+
BLAS.hpmv!('U', α, AP, x, β, y_result_blas_upper)
240+
@test y_result_juliay_result_blas_upper
241+
end
242+
end
243+
203244
#trsm
204245
A = triu(rand(elty,n,n))
205246
B = rand(elty,(n,n))

0 commit comments

Comments
 (0)