-
Notifications
You must be signed in to change notification settings - Fork 208
feat: Add generalized lagtm routine supporting arbitrary values for alpha and beta #1068
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
base: master
Are you sure you want to change the base?
Changes from 5 commits
27906b3
d2d9aef
c6b1a33
d18b50c
d50fd87
608f8ad
a27ebf8
3428d45
21a5435
ffe1a6f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,3 @@ | ||
| ADD_EXAMPLE(specialmatrices_dp_spmv) | ||
| ADD_EXAMPLE(specialmatrices_cdp_spmv) | ||
| ADD_EXAMPLE(tridiagonal_dp_type) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| program example_tridiagonal_matrix_cdp | ||
| use stdlib_linalg_constants, only: dp | ||
| use stdlib_specialmatrices, only: tridiagonal_cdp_type, tridiagonal, dense, spmv | ||
| implicit none | ||
|
|
||
| integer, parameter :: n = 5 | ||
| type(tridiagonal_cdp_type) :: A | ||
| complex(dp) :: dl(n-1), dv(n), du(n-1) | ||
| complex(dp) :: x(n), y(n), y_dense(n) | ||
| integer :: i | ||
| complex(dp) :: alpha, beta | ||
|
|
||
| dl = [(cmplx(i,i, dp), i=1, n - 1)] | ||
| dv = [(cmplx(2*i,2*i, dp), i=1, n)] | ||
| du = [(cmplx(3*i,3*i, dp), i=1, n - 1)] | ||
|
|
||
| A = tridiagonal(dl, dv, du) | ||
|
|
||
| x = (1.0_dp, 0.0_dp) | ||
| y = (3.0_dp, -7.0_dp) | ||
| y_dense = (0.0_dp, 0.0_dp) | ||
| alpha = cmplx(2.0_dp, 3.0_dp) | ||
| beta = cmplx(-1.0_dp, 5.0_dp) | ||
|
|
||
| y_dense = alpha * matmul(dense(A), x) + beta * y | ||
| call spmv(A, x, y, alpha, beta) | ||
|
|
||
| print *, 'dense :', y_dense | ||
| print *, 'Tridiagonal :', y | ||
| end program example_tridiagonal_matrix_cdp |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,10 @@ | ||
| set(lapack_extended_fppFiles | ||
| ../stdlib_kinds.fypp | ||
| stdlib_extended_lapack_base.fypp | ||
| stdlib_extended_lapack.fypp | ||
| ) | ||
| set(lapack_extended_cppFiles | ||
| ../stdlib_linalg_constants.fypp | ||
| ) | ||
|
|
||
| configure_stdlib_target(lapack_extended "" lapack_extended_fppFiles lapack_extended_cppFiles) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,85 @@ | ||
| #:include "common.fypp" | ||
| #:set R_KINDS_TYPES = list(zip(REAL_KINDS, REAL_TYPES, REAL_SUFFIX)) | ||
| #:set C_KINDS_TYPES = list(zip(CMPLX_KINDS, CMPLX_TYPES, CMPLX_SUFFIX)) | ||
| #:set KINDS_TYPES = R_KINDS_TYPES+C_KINDS_TYPES | ||
|
|
||
| submodule(stdlib_extended_lapack_base) stdlib_extended_lapack | ||
| implicit none | ||
| contains | ||
| #:for ik,it,ii in LINALG_INT_KINDS_TYPES | ||
| #:for k1,t1,s1 in KINDS_TYPES | ||
| pure module subroutine stdlib${ii}$_glagtm_${s1}$(trans, n, nrhs, alpha, dl, d, du, x, ldx, beta, b, ldb) | ||
| character, intent(in) :: trans | ||
| integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs | ||
| ${t1}$, intent(in) :: alpha, beta | ||
| ${t1}$, intent(inout) :: b(ldb,*) | ||
| ${t1}$, intent(in) :: d(*), dl(*), du(*), x(ldx,*) | ||
|
|
||
| ! Internal variables. | ||
| integer(${ik}$) :: i, j | ||
| ${t1}$ :: temp | ||
| if(n == 0) then | ||
| return | ||
| endif | ||
| if(beta == 0.0_${k1}$) then | ||
| b(1:n, 1:nrhs) = 0.0_${k1}$ | ||
| else | ||
| b(1:n, 1:nrhs) = beta * b(1:n, 1:nrhs) | ||
| end if | ||
|
|
||
| if(trans == 'N') then | ||
| do j = 1, nrhs | ||
| if(n == 1_${ik}$) then | ||
| temp = d(1_${ik}$) * x(1_${ik}$, j) | ||
| b(1_${ik}$, j) = b(1_${ik}$, j) + alpha * temp | ||
| else | ||
| temp = d(1_${ik}$) * x(1_${ik}$, j) + du(1_${ik}$) * x(2_${ik}$, j) | ||
| b(1_${ik}$, j) = b(1_${ik}$, j) + alpha * temp | ||
| do i = 2, n - 1 | ||
| temp = dl(i - 1) * x(i - 1, j) + d(i) * x(i, j) + du(i) * x(i + 1, j) | ||
| b(i, j) = b (i, j) + alpha * temp | ||
| end do | ||
| temp = dl(n - 1) * x(n - 1, j) + d(n) * x(n, j) | ||
| b(n, j) = b(n, j) + alpha * temp | ||
| end if | ||
| end do | ||
| #:if t1.startswith('complex') | ||
| else if(trans == 'C') then | ||
| do j = 1, nrhs | ||
| if(n == 1_${ik}$) then | ||
| temp = conjg(d(1_${ik}$)) * x(1_${ik}$, j) | ||
| b(1_${ik}$, j) = b(1_${ik}$, j) + alpha * temp | ||
| else | ||
| temp = conjg(d(1_${ik}$)) * x(1_${ik}$, j) + conjg(dl(1_${ik}$)) * x(2_${ik}$, j) | ||
| b(1_${ik}$, j) = b(1_${ik}$, j) + alpha * temp | ||
| do i = 2, n - 1 | ||
| temp = conjg(du(i - 1)) * x(i - 1, j) + conjg(d(i)) * x(i, j) + conjg(dl(i)) * x(i + 1, j) | ||
| b(i, j) = b (i, j) + alpha * temp | ||
jalvesz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| end do | ||
| temp = conjg(du(n - 1)) * x(n - 1, j) + conjg(d(n)) * x(n, j) | ||
| b(n, j) = b(n, j) + alpha * temp | ||
| end if | ||
| end do | ||
| #:endif | ||
| else | ||
| do j = 1, nrhs | ||
| if(n == 1_${ik}$) then | ||
| temp = d(1_${ik}$) * x(1_${ik}$, j) | ||
| b(1_${ik}$, j) = b(1_${ik}$, j) + alpha * temp | ||
| else | ||
| temp = d(1_${ik}$) * x(1_${ik}$, j) + dl(1_${ik}$) * x(2_${ik}$, j) | ||
| b(1_${ik}$, j) = b(1_${ik}$, j) + alpha * temp | ||
| do i = 2, n - 1 | ||
| temp = du(i - 1) * x(i - 1, j) + d(i) * x(i, j) + dl(i) * x(i + 1, j) | ||
| b(i, j) = b (i, j) + alpha * temp | ||
jalvesz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| end do | ||
| temp = du(n - 1) * x(n - 1, j) + d(n) * x(n, j) | ||
| b(n, j) = b(n, j) + alpha * temp | ||
| end if | ||
| end do | ||
| end if | ||
| end subroutine stdlib${ii}$_glagtm_${s1}$ | ||
| #:endfor | ||
| #:endfor | ||
|
|
||
| end submodule | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| #:include "common.fypp" | ||
| #:set R_KINDS_TYPES = list(zip(REAL_KINDS, REAL_TYPES, REAL_SUFFIX)) | ||
| #:set C_KINDS_TYPES = list(zip(CMPLX_KINDS, CMPLX_TYPES, CMPLX_SUFFIX)) | ||
| #:set KINDS_TYPES = R_KINDS_TYPES+C_KINDS_TYPES | ||
| module stdlib_extended_lapack_base | ||
| use stdlib_linalg_constants | ||
| implicit none | ||
|
|
||
| interface glagtm | ||
| #:for ik,it,ii in LINALG_INT_KINDS_TYPES | ||
| #:for k1,t1,s1 in KINDS_TYPES | ||
| pure module subroutine stdlib${ii}$_glagtm_${s1}$(trans, n, nrhs, alpha, dl, d, du, x, ldx, beta, b, ldb) | ||
| character, intent(in) :: trans | ||
| integer(${ik}$), intent(in) :: ldb, ldx, n, nrhs | ||
| ${t1}$, intent(in) :: alpha, beta | ||
| ${t1}$, intent(inout) :: b(ldb,*) | ||
| ${t1}$, intent(in) :: d(*), dl(*), du(*), x(ldx,*) | ||
| end subroutine stdlib${ii}$_glagtm_${s1}$ | ||
| #:endfor | ||
| #:endfor | ||
| end interface | ||
| end module |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -155,14 +155,16 @@ submodule (stdlib_specialmatrices) tridiagonal_matrices | |||||||||||||||||||||||||||||||
| type(tridiagonal_${s1}$_type), intent(in) :: A | ||||||||||||||||||||||||||||||||
| ${t1}$, intent(in), contiguous, target :: x${ranksuffix(rank)}$ | ||||||||||||||||||||||||||||||||
| ${t1}$, intent(inout), contiguous, target :: y${ranksuffix(rank)}$ | ||||||||||||||||||||||||||||||||
| real(${k1}$), intent(in), optional :: alpha | ||||||||||||||||||||||||||||||||
| real(${k1}$), intent(in), optional :: beta | ||||||||||||||||||||||||||||||||
| ${t1}$, intent(in), optional :: alpha | ||||||||||||||||||||||||||||||||
| ${t1}$, intent(in), optional :: beta | ||||||||||||||||||||||||||||||||
| character(1), intent(in), optional :: op | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| ! Internal variables. | ||||||||||||||||||||||||||||||||
| real(${k1}$) :: alpha_, beta_ | ||||||||||||||||||||||||||||||||
| ${t1}$ :: alpha_, beta_ | ||||||||||||||||||||||||||||||||
| integer(ilp) :: n, nrhs, ldx, ldy | ||||||||||||||||||||||||||||||||
| character(1) :: op_ | ||||||||||||||||||||||||||||||||
| logical :: is_alpha_special, is_beta_special | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| #:if rank == 1 | ||||||||||||||||||||||||||||||||
| ${t1}$, pointer :: xmat(:, :), ymat(:, :) | ||||||||||||||||||||||||||||||||
| #:endif | ||||||||||||||||||||||||||||||||
|
|
@@ -172,16 +174,35 @@ submodule (stdlib_specialmatrices) tridiagonal_matrices | |||||||||||||||||||||||||||||||
| beta_ = 0.0_${k1}$ ; if (present(beta)) beta_ = beta | ||||||||||||||||||||||||||||||||
| op_ = "N" ; if (present(op)) op_ = op | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| is_alpha_special = (alpha_ == 1.0_${k1}$ .or. alpha_ == 0.0_${k1}$ .or. alpha_ == -1.0_${k1}$) | ||||||||||||||||||||||||||||||||
| is_beta_special = (beta_ == 1.0_${k1}$ .or. beta_ == 0.0_${k1}$ .or. beta_ == -1.0_${k1}$) | ||||||||||||||||||||||||||||||||
|
Comment on lines
174
to
180
|
||||||||||||||||||||||||||||||||
| is_alpha_special = (alpha_ == 1.0_${k1}$ .or. alpha_ == 0.0_${k1}$ .or. alpha_ == -1.0_${k1}$) | |
| is_beta_special = (beta_ == 1.0_${k1}$ .or. beta_ == 0.0_${k1}$ .or. beta_ == -1.0_${k1}$) | |
| #:if t1.startswith('complex') | |
| is_alpha_special = ((real(alpha_) == 1.0_${k1}$ .and. aimag(alpha_) == 0.0_${k1}$) .or. & | |
| (real(alpha_) == 0.0_${k1}$ .and. aimag(alpha_) == 0.0_${k1}$) .or. & | |
| (real(alpha_) == -1.0_${k1}$ .and. aimag(alpha_) == 0.0_${k1}$)) | |
| is_beta_special = ((real(beta_) == 1.0_${k1}$ .and. aimag(beta_) == 0.0_${k1}$) .or. & | |
| (real(beta_) == 0.0_${k1}$ .and. aimag(beta_) == 0.0_${k1}$) .or. & | |
| (real(beta_) == -1.0_${k1}$ .and. aimag(beta_) == 0.0_${k1}$)) | |
| #:else | |
| is_alpha_special = (alpha_ == 1.0_${k1}$ .or. alpha_ == 0.0_${k1}$ .or. alpha_ == -1.0_${k1}$) | |
| is_beta_special = (beta_ == 1.0_${k1}$ .or. beta_ == 0.0_${k1}$ .or. beta_ == -1.0_${k1}$) | |
| #:endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An easier solution is to use stdlib_constants where constants zero and one have been added for all kinds. So simply replacing the real values with the respective constants would do the job.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
An easier solution is to use
stdlib_constantswhere constants zero and one have been added for all kinds. So simply replacing the real values with the respective constants would do the job.
Another solution would be to wrap those two lines and the declaration of is_alpha_special and is_beta_special in an #:if t1.startswith('real') block. Then we can avoid the checks for is_alpha_special and is_beta_special in case of complex types. This works because for complex types we always call glagtm regardless of the values of alpha and beta.
Let me know which approach you’d prefer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sounds good to me!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inconsistent spacing: extra space between 'b' and '(i, j)' compared to other lines.