dtrmm(3f) - [BLAS:DOUBLE_BLAS_LEVEL3]
subroutine dtrmm(side,uplo,transa,diag,m,n,alpha,a,lda,b,ldb)
.. Scalar Arguments ..
double precision,intent(in) :: alpha
integer,intent(in) :: lda,ldb,m,n
character,intent(in) :: diag,side,transa,uplo
..
.. Array Arguments ..
double precision,intent(in) :: a(lda,*)
double precision,intent(inout) :: b(ldb,*)
..
DTRMM performs one of the matrix-matrix operations
B := alpha*op( A )*B, or B := alpha*B*op( A ),
where alpha is a scalar, B is an m by n matrix, A is a unit, or non-unit, upper or lower triangular matrix and op( A ) is one of
op( A ) = A or op( A ) = A**T.
SIDE
SIDE is CHARACTER*1
On entry, SIDE specifies whether op( A ) multiplies B from
the left or right as follows:
SIDE = 'L' or 'l' B := alpha*op( A )*B.
SIDE = 'R' or 'r' B := alpha*B*op( A ).
UPLO
UPLO is CHARACTER*1
On entry, UPLO specifies whether the matrix A is an upper or
lower triangular matrix as follows:
UPLO = 'U' or 'u' A is an upper triangular matrix.
UPLO = 'L' or 'l' A is a lower triangular matrix.
TRANSA
TRANSA is CHARACTER*1
On entry, TRANSA specifies the form of op( A ) to be used in
the matrix multiplication as follows:
TRANSA = 'N' or 'n' op( A ) = A.
TRANSA = 'T' or 't' op( A ) = A**T.
TRANSA = 'C' or 'c' op( A ) = A**T.
DIAG
DIAG is CHARACTER*1
On entry, DIAG specifies whether or not A is unit triangular
as follows:
DIAG = 'U' or 'u' A is assumed to be unit triangular.
DIAG = 'N' or 'n' A is not assumed to be unit
triangular.
M
M is INTEGER
On entry, M specifies the number of rows of B. M must be at
least zero.
N
N is INTEGER
On entry, N specifies the number of columns of B. N must be
at least zero.
ALPHA
ALPHA is DOUBLE PRECISION.
On entry, ALPHA specifies the scalar alpha. When alpha is
zero then A is not referenced and B need not be set before
entry.
A
A is DOUBLE PRECISION array, dimension ( LDA, k ), where k is m
when SIDE = 'L' or 'l' and is n when SIDE = 'R' or 'r'.
Before entry with UPLO = 'U' or 'u', the leading k by k
upper triangular part of the array A must contain the upper
triangular matrix and the strictly lower triangular part of
A is not referenced.
Before entry with UPLO = 'L' or 'l', the leading k by k
lower triangular part of the array A must contain the lower
triangular matrix and the strictly upper triangular part of
A is not referenced.
Note that when DIAG = 'U' or 'u', the diagonal elements of
A are not referenced either, but are assumed to be unity.
LDA
LDA is INTEGER
On entry, LDA specifies the first dimension of A as declared
in the calling (sub) program. When SIDE = 'L' or 'l' then
LDA must be at least max( 1, m ), when SIDE = 'R' or 'r'
then LDA must be at least max( 1, n ).
B
B is DOUBLE PRECISION array, dimension ( LDB, N )
Before entry, the leading m by n part of the array B must
contain the matrix B, and on exit is overwritten by the
transformed matrix.
LDB
LDB is INTEGER
On entry, LDB specifies the first dimension of B as declared
in the calling (sub) program. LDB must be at least
max( 1, m ).
date:December 2016
FURTHER DETAILS
Level 3 Blas routine.
– Written on 8-February-1989. Jack Dongarra, Argonne National Laboratory. Iain Duff, AERE Harwell. Jeremy Du Croz, Numerical Algorithms Group Ltd. Sven Hammarling, Numerical Algorithms Group Ltd.
Online html documentation available at
http://www.netlib.org/lapack/explore-html/
Type | Intent | Optional | Attributes | Name | ||
---|---|---|---|---|---|---|
character(len=1), | intent(in) | :: | side | |||
character(len=1), | intent(in) | :: | uplo | |||
character(len=1), | intent(in) | :: | transa | |||
character(len=1), | intent(in) | :: | diag | |||
integer, | intent(in) | :: | m | |||
integer, | intent(in) | :: | n | |||
double precision, | intent(in) | :: | alpha | |||
double precision, | intent(in) | :: | a(lda,*) | |||
integer, | intent(in) | :: | lda | |||
double precision, | intent(inout) | :: | b(ldb,*) | |||
integer, | intent(in) | :: | ldb |
Type | Visibility | Attributes | Name | Initial | |||
---|---|---|---|---|---|---|---|
integer, | public | :: | i | ||||
integer, | public | :: | info | ||||
integer, | public | :: | j | ||||
integer, | public | :: | k | ||||
logical, | public | :: | lside | ||||
logical, | public | :: | nounit | ||||
integer, | public | :: | nrowa | ||||
double precision, | public, | parameter | :: | one | = | 1.0d+0 | |
double precision, | public | :: | temp | ||||
logical, | public | :: | upper | ||||
double precision, | public, | parameter | :: | zero | = | 0.0d+0 |
subroutine dtrmm(side,uplo,transa,diag,m,n,alpha,a,lda,b,ldb)
implicit none
!
! -- Reference BLAS level3 routine (version 3.7.0) --
! -- Reference BLAS is a software package provided by Univ. of Tennessee, --
! -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..--
! December 2016
!
! .. Scalar Arguments ..
double precision,intent(in) :: alpha
integer,intent(in) :: lda,ldb,m,n
character,intent(in) :: diag,side,transa,uplo
! ..
! .. Array Arguments ..
double precision,intent(in) :: a(lda,*)
double precision,intent(inout) :: b(ldb,*)
! ..
!
! =====================================================================
!
! .. External Functions ..
! ..
! .. External Subroutines ..
! ..
! .. Intrinsic Functions ..
intrinsic max
! ..
! .. Local Scalars ..
double precision temp
integer i,info,j,k,nrowa
logical lside,nounit,upper
! ..
! .. Parameters ..
double precision one,zero
parameter (one=1.0d+0,zero=0.0d+0)
! ..
!
! Test the input parameters.
!
lside = lsame(side,'L')
if (lside) then
nrowa = m
else
nrowa = n
endif
nounit = lsame(diag,'N')
upper = lsame(uplo,'U')
!
info = 0
if ((.not.lside) .and. (.not.lsame(side,'R'))) then
info = 1
elseif ((.not.upper) .and. (.not.lsame(uplo,'L'))) then
info = 2
elseif ((.not.lsame(transa,'N')) .and. (.not.lsame(transa,'T')) .and. (.not.lsame(transa,'C'))) then
info = 3
elseif ((.not.lsame(diag,'U')) .and. (.not.lsame(diag,'N'))) then
info = 4
elseif (m.lt.0) then
info = 5
elseif (n.lt.0) then
info = 6
elseif (lda.lt.max(1,nrowa)) then
info = 9
elseif (ldb.lt.max(1,m)) then
info = 11
endif
if (info.ne.0) then
call xerbla('DTRMM ',info)
return
endif
!
! Quick return if possible.
!
if (m.eq.0 .or. n.eq.0) return
!
! And when alpha.eq.zero.
!
if (alpha.eq.zero) then
b(1:m,1:n) = zero
return
endif
!
! Start the operations.
!
if (lside) then
if (lsame(transa,'N')) then
!
! Form B := alpha*A*B.
!
if (upper) then
do j = 1,n
do k = 1,m
if (b(k,j).ne.zero) then
temp = alpha*b(k,j)
do i = 1,k - 1
b(i,j) = b(i,j) + temp*a(i,k)
enddo
if (nounit) temp = temp*a(k,k)
b(k,j) = temp
endif
enddo
enddo
else
do j = 1,n
do k = m,1,-1
if (b(k,j).ne.zero) then
temp = alpha*b(k,j)
b(k,j) = temp
if (nounit) b(k,j) = b(k,j)*a(k,k)
do i = k + 1,m
b(i,j) = b(i,j) + temp*a(i,k)
enddo
endif
enddo
enddo
endif
else
!
! Form B := alpha*A**T*B.
!
if (upper) then
do j = 1,n
do i = m,1,-1
temp = b(i,j)
if (nounit) temp = temp*a(i,i)
do k = 1,i - 1
temp = temp + a(k,i)*b(k,j)
enddo
b(i,j) = alpha*temp
enddo
enddo
else
do j = 1,n
do i = 1,m
temp = b(i,j)
if (nounit) temp = temp*a(i,i)
do k = i + 1,m
temp = temp + a(k,i)*b(k,j)
enddo
b(i,j) = alpha*temp
enddo
enddo
endif
endif
else
if (lsame(transa,'N')) then
!
! Form B := alpha*B*A.
!
if (upper) then
do j = n,1,-1
temp = alpha
if (nounit) temp = temp*a(j,j)
b(1:m,j) = temp*b(1:m,j)
do k = 1,j - 1
if (a(k,j).ne.zero) then
temp = alpha*a(k,j)
b(1:m,j) = b(1:m,j) + temp*b(1:m,k)
endif
enddo
enddo
else
do j = 1,n
temp = alpha
if (nounit) temp = temp*a(j,j)
b(1:m,j) = temp*b(1:m,j)
do k = j + 1,n
if (a(k,j).ne.zero) then
temp = alpha*a(k,j)
b(1:m,j) = b(1:m,j) + temp*b(1:m,k)
endif
enddo
enddo
endif
else
!
! Form B := alpha*B*A**T.
!
if (upper) then
do k = 1,n
do j = 1,k - 1
if (a(j,k).ne.zero) then
temp = alpha*a(j,k)
b(1:m,j) = b(1:m,j) + temp*b(1:m,k)
endif
enddo
temp = alpha
if (nounit) temp = temp*a(k,k)
if (temp.ne.one) then
b(1:m,k) = temp*b(1:m,k)
endif
enddo
else
do k = n,1,-1
do j = k + 1,n
if (a(j,k).ne.zero) then
temp = alpha*a(j,k)
b(1:m,j) = b(1:m,j) + temp*b(1:m,k)
endif
enddo
temp = alpha
if (nounit) temp = temp*a(k,k)
if (temp.ne.one) then
b(1:m,k) = temp*b(1:m,k)
endif
enddo
endif
endif
endif
!
end subroutine dtrmm