Skip to content

Commit ae336ab

Browse files
authored
add spr! to LinearAlgebra.BLAS (#42830)
1 parent a21cc80 commit ae336ab

File tree

3 files changed

+110
-0
lines changed

3 files changed

+110
-0
lines changed

NEWS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ Standard library changes
8989
#### Package Manager
9090

9191
#### LinearAlgebra
92+
* The BLAS submodule now supports the level-2 BLAS subroutine `spr!` ([#42830]).
9293

9394
#### Markdown
9495

stdlib/LinearAlgebra/src/blas.jl

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export
3333
sbmv!,
3434
sbmv,
3535
spmv!,
36+
spr!,
3637
symv!,
3738
symv,
3839
trsv!,
@@ -1145,6 +1146,71 @@ Return the updated `y`.
11451146
"""
11461147
spmv!
11471148

1149+
### spr!, (SP) symmetric packed matrix-vector operation defined as A := alpha*x*x' + A
1150+
for (fname, elty) in ((:dspr_, :Float64),
1151+
(:sspr_, :Float32))
1152+
@eval begin
1153+
function spr!(uplo::AbstractChar,
1154+
n::Integer,
1155+
α::$elty,
1156+
x::Union{Ptr{$elty}, AbstractArray{$elty}},
1157+
incx::Integer,
1158+
AP::Union{Ptr{$elty}, AbstractArray{$elty}})
1159+
1160+
ccall((@blasfunc($fname), libblastrampoline), Cvoid,
1161+
(Ref{UInt8}, # uplo,
1162+
Ref{BlasInt}, # n,
1163+
Ref{$elty}, # α,
1164+
Ptr{$elty}, # x,
1165+
Ref{BlasInt}, # incx,
1166+
Ptr{$elty}, # AP,
1167+
Clong), # length of uplo
1168+
uplo,
1169+
n,
1170+
α,
1171+
x,
1172+
incx,
1173+
AP,
1174+
1)
1175+
return AP
1176+
end
1177+
end
1178+
end
1179+
1180+
function spr!(uplo::AbstractChar,
1181+
α::Real, x::Union{DenseArray{T}, AbstractVector{T}},
1182+
AP::Union{DenseArray{T}, AbstractVector{T}}) where {T <: BlasReal}
1183+
require_one_based_indexing(AP, x)
1184+
N = length(x)
1185+
if 2*length(AP) < N*(N + 1)
1186+
throw(DimensionMismatch("Packed symmetric matrix A has size smaller than length(x) = $(N)."))
1187+
end
1188+
return spr!(uplo, N, convert(T, α), x, stride(x, 1), AP)
1189+
end
1190+
1191+
"""
1192+
spr!(uplo, α, x, AP)
1193+
1194+
Update matrix `A` as `α*A*x*x'`, where `A` is a symmetric matrix provided
1195+
in packed format `AP` and `x` is a vector.
1196+
1197+
With `uplo = 'U'`, the array AP must contain the upper triangular part of the
1198+
symmetric matrix packed sequentially, column by column, so that `AP[1]`
1199+
contains `A[1, 1]`, `AP[2]` and `AP[3]` contain `A[1, 2]` and `A[2, 2]`
1200+
respectively, and so on.
1201+
1202+
With `uplo = 'L'`, the array AP must contain the lower triangular part of the
1203+
symmetric matrix packed sequentially, column by column, so that `AP[1]`
1204+
contains `A[1, 1]`, `AP[2]` and `AP[3]` contain `A[2, 1]` and `A[3, 1]`
1205+
respectively, and so on.
1206+
1207+
The scalar input `α` must be real.
1208+
1209+
The array inputs `x` and `AP` must all be of `Float32` or `Float64` type.
1210+
Return the updated `AP`.
1211+
"""
1212+
spr!
1213+
11481214
### hbmv, (HB) Hermitian banded matrix-vector multiplication
11491215
for (fname, elty) in ((:zhbmv_,:ComplexF64),
11501216
(:chbmv_,:ComplexF32))

stdlib/LinearAlgebra/test/blas.jl

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,49 @@ Random.seed!(100)
314314
end
315315
end
316316

317+
# spr!
318+
if elty in (Float32, Float64)
319+
@testset "spr! $elty" begin
320+
α = rand(elty)
321+
M = rand(elty, n, n)
322+
AL = Symmetric(M, :L)
323+
AU = Symmetric(M, :U)
324+
x = rand(elty, n)
325+
326+
function pack(A, uplo)
327+
AP = elty[]
328+
for j in 1:n
329+
for i in (uplo==:L ? (j:n) : (1:j))
330+
push!(AP, A[i,j])
331+
end
332+
end
333+
return AP
334+
end
335+
336+
ALP_result_julia_lower = pack*x*x' + AL, :L)
337+
ALP_result_blas_lower = pack(AL, :L)
338+
BLAS.spr!('L', α, x, ALP_result_blas_lower)
339+
@test ALP_result_julia_lower ALP_result_blas_lower
340+
ALP_result_blas_lower = append!(pack(AL, :L), ones(elty, 10))
341+
BLAS.spr!('L', α, x, ALP_result_blas_lower)
342+
@test ALP_result_julia_lower ALP_result_blas_lower[1:end-10]
343+
ALP_result_blas_lower = reshape(pack(AL, :L), 1, length(ALP_result_julia_lower), 1)
344+
BLAS.spr!('L', α, x, ALP_result_blas_lower)
345+
@test ALP_result_julia_lower vec(ALP_result_blas_lower)
346+
347+
AUP_result_julia_upper = pack*x*x' + AU, :U)
348+
AUP_result_blas_upper = pack(AU, :U)
349+
BLAS.spr!('U', α, x, AUP_result_blas_upper)
350+
@test AUP_result_julia_upper AUP_result_blas_upper
351+
AUP_result_blas_upper = append!(pack(AU, :U), ones(elty, 10))
352+
BLAS.spr!('U', α, x, AUP_result_blas_upper)
353+
@test AUP_result_julia_upper AUP_result_blas_upper[1:end-10]
354+
AUP_result_blas_upper = reshape(pack(AU, :U), 1, length(AUP_result_julia_upper), 1)
355+
BLAS.spr!('U', α, x, AUP_result_blas_upper)
356+
@test AUP_result_julia_upper vec(AUP_result_blas_upper)
357+
end
358+
end
359+
317360
#trsm
318361
A = triu(rand(elty,n,n))
319362
B = rand(elty,(n,n))

0 commit comments

Comments
 (0)