subroutine cgemm ( transa, transb, m, n, k, alpha, a, lda, b, ldb, beta, c, & ldc ) !*****************************************************************************80 ! !! CGEMM performs C:=alpha*A*B+beta*C, A, B, C rectangular. ! ! CGEMM performs one of the matrix-matrix operations ! ! C := alpha*op( A )*op( B ) + beta*C, ! ! where op( X ) is one of ! ! op( X ) = X or op( X ) = X' or op( X ) = conjg( X' ), ! ! alpha and beta are scalars, and A, B and C are matrices, with op( A ) ! an m by k matrix, op( B ) a k by n matrix and C an m by n matrix. ! ! Parameters: ! ! TRANSA - character. ! 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'. ! ! TRANSA = 'C' or 'c', op( A ) = conjg( A' ). ! ! Unchanged on exit. ! ! TRANSB - character. ! On entry, TRANSB specifies the form of op( B ) to be used in ! the matrix multiplication as follows: ! ! TRANSB = 'N' or 'n', op( B ) = B. ! ! TRANSB = 'T' or 't', op( B ) = B'. ! ! TRANSB = 'C' or 'c', op( B ) = conjg( B' ). ! ! Unchanged on exit. ! ! M - integer. ! On entry, M specifies the number of rows of the matrix ! op( A ) and of the matrix C. M must be at least zero. ! Unchanged on exit. ! ! N - integer. ! On entry, N specifies the number of columns of the matrix ! op( B ) and the number of columns of the matrix C. N must be ! at least zero. ! Unchanged on exit. ! ! K - integer. ! On entry, K specifies the number of columns of the matrix ! op( A ) and the number of rows of the matrix op( B ). K must ! be at least zero. ! Unchanged on exit. ! ! ALPHA - complex . ! On entry, ALPHA specifies the scalar alpha. ! Unchanged on exit. ! ! A - complex array of DIMENSION ( LDA, ka ), where ka is ! k when TRANSA = 'N' or 'n', and is m otherwise. ! Before entry with TRANSA = 'N' or 'n', the leading m by k ! part of the array A must contain the matrix A, otherwise ! the leading k by m part of the array A must contain the ! matrix A. ! Unchanged on exit. ! ! LDA - integer. ! On entry, LDA specifies the first dimension of A as declared ! in the calling (sub) program. When TRANSA = 'N' or 'n' then ! LDA must be at least max( 1, m ), otherwise LDA must be at ! least max( 1, k ). ! Unchanged on exit. ! ! B - complex array of DIMENSION ( LDB, kb ), where kb is ! n when TRANSB = 'N' or 'n', and is k otherwise. ! Before entry with TRANSB = 'N' or 'n', the leading k by n ! part of the array B must contain the matrix B, otherwise ! the leading n by k part of the array B must contain the ! matrix B. ! Unchanged on exit. ! ! LDB - integer. ! On entry, LDB specifies the first dimension of B as declared ! in the calling (sub) program. When TRANSB = 'N' or 'n' then ! LDB must be at least max( 1, k ), otherwise LDB must be at ! least max( 1, n ). ! Unchanged on exit. ! ! BETA - complex . ! On entry, BETA specifies the scalar beta. When BETA is ! supplied as zero then C need not be set on input. ! Unchanged on exit. ! ! Input/output, complex C( LDC, n ). ! Before input, the leading m by n part of the array C must ! contain the matrix C, except when beta is zero, in which ! case C need not be set on entry. ! On output, the array C is overwritten by the m by n matrix ! ( alpha*op( A )*op( B ) + beta*C ). ! ! LDC - integer. ! On entry, LDC specifies the first dimension of C as declared ! in the calling (sub) program. LDC must be at least ! max( 1, m ). ! Unchanged on exit. ! implicit none integer lda integer ldb integer ldc integer k integer m integer n character transa character transb complex alpha, beta complex a( lda, * ), b( ldb, * ), c( ldc, * ) logical lsame logical conja, conjb, nota, notb integer i, info, j, l, ncola, nrowa, nrowb complex temp complex, parameter :: one = ( 1.0E+00, 0.0E+00 ) complex, parameter :: zero = ( 0.0E+00, 0.0E+00 ) ! ! Set NOTA and NOTB as true if A and B respectively are not ! conjugated or transposed, set CONJA and CONJB as true if A and ! B respectively are to be transposed but not conjugated and set ! NROWA, NCOLA and NROWB as the number of rows and columns of A ! and the number of rows of B respectively. ! nota = lsame ( transa, 'N' ) notb = lsame ( transb, 'N' ) conja = lsame ( transa, 'C' ) conjb = lsame ( transb, 'C' ) if ( nota ) then nrowa = m ncola = k else nrowa = k ncola = m end if if ( notb ) then nrowb = k else nrowb = n end if ! ! Test the input. ! info = 0 if ( ( .not.nota ) .and. & ( .not.conja ) .and. & ( .not.lsame ( transa, 'T' ) ) ) then info = 1 else if ( ( .not.notb ) .and. & ( .not.conjb ) .and. & ( .not.lsame ( transb, 'T' ) ) ) then info = 2 else if ( m < 0 ) then info = 3 else if ( n < 0 ) then info = 4 else if ( k < 0 ) then info = 5 else if ( lda < max ( 1, nrowa ) ) then info = 8 else if ( ldb < max ( 1, nrowb ) ) then info = 10 else if ( ldc < max ( 1, m ) ) then info = 13 end if if ( info /= 0 ) then call xerbla ( 'cgemm ', info ) return end if ! ! Quick return if possible. ! if ( ( m == 0 ).or.( n == 0 ) .or. & ( ( ( alpha == zero ).or.( k == 0 ) ) .and. ( beta == one ) ) ) then return end if ! ! And when ALPHA == zero. ! if ( alpha == zero ) then if ( beta == zero ) then c(1:m,1:n) = zero else c(1:m,1:n) = beta * c(1:m,1:n) end if return end if ! ! Start the operations. ! if ( notb ) then if ( nota ) then ! ! Form C := alpha*A * b + beta*C. ! do j = 1, n if ( beta == zero ) then c(1:m,j) = zero else if ( beta/= one ) then c(1:m,j) = beta * c(1:m,j) end if do l = 1, k if ( b(l,j) /= zero ) then temp = alpha * b(l,j) c(1:m,j) = c(1:m,j) + temp * a(1:m,l) end if end do end do else if ( conja ) then ! ! Form C := alpha*conjg( A' ) * b + beta*C. ! do j = 1, n do i = 1, m temp = zero do l = 1, k temp = temp + conjg ( a(l,i) ) * b(l,j) end do if ( beta == zero ) then c(i,j) = alpha * temp else c(i,j) = alpha * temp + beta * c(i,j) end if end do end do else ! ! Form C := alpha*A' * b + beta*C ! do j = 1, n do i = 1, m temp = dot_product ( a(1:k,i), b(1:k,j) ) if ( beta == zero ) then c(i,j) = alpha * temp else c(i,j) = alpha * temp + beta * c(i,j) end if end do end do end if else if ( nota ) then if ( conjb ) then ! ! Form C := alpha*A*conjg( B' ) + beta*C. ! do j = 1, n if ( beta == zero ) then c(1:m,j) = zero else if ( beta/= one ) then c(1:m,j) = beta * c(1:m,j) end if do l = 1, k if ( b(j,l) /= zero ) then temp = alpha * conjg ( b(j,l) ) c(1:m,j) = c(1:m,j) + temp * a(1:m,l) end if end do end do else ! ! Form C := alpha*A * b' + beta*C ! do j = 1, n if ( beta == zero ) then c(1:m,j) = zero else if ( beta /= one ) then c(1:m,j) = beta * c(1:m,j) end if do l = 1, k if ( b(j,l) /= zero ) then temp = alpha * b(j,l) c(1:m,j) = c(1:m,j) + temp * a(1:m,l) end if end do end do end if else if ( conja ) then if ( conjb ) then ! ! Form C := alpha*conjg( A' )*conjg( B' ) + beta*C. ! do j = 1, n do i = 1, m temp = zero do l = 1, k temp = temp + conjg ( a(l,i) ) * conjg ( b(j,l) ) end do if ( beta == zero ) then c(i,j) = alpha * temp else c(i,j) = alpha * temp + beta * c(i,j) end if end do end do else ! ! Form C := alpha*conjg( A' ) * b' + beta*C ! do j = 1, n do i = 1, m temp = zero do l = 1, k temp = temp + conjg ( a(l,i) ) * b(j,l) end do if ( beta == zero ) then c(i,j) = alpha * temp else c(i,j) = alpha * temp + beta * c(i,j) end if end do end do end if else if ( conjb ) then ! ! Form C := alpha*A'*conjg( B' ) + beta*C ! do j = 1, n do i = 1, m temp = zero do l = 1, k temp = temp + a(l,i)*conjg ( b(j,l) ) end do if ( beta == zero ) then c(i,j) = alpha * temp else c(i,j) = alpha * temp + beta * c(i,j) end if end do end do else ! ! Form C := alpha*A' * b' + beta*C ! do j = 1, n do i = 1, m temp = zero do l = 1, k temp = temp + a(l,i) * b(j,l) end do if ( beta == zero ) then c(i,j) = alpha * temp else c(i,j) = alpha * temp + beta * c(i,j) end if end do end do end if end if return end subroutine chemm ( side, uplo, m, n, alpha, a, lda, b, ldb, beta, c, ldc ) !*****************************************************************************80 ! !! CHEMM performs C:= alpha*A*B+beta*C, for A hermitian. ! ! CHEMM performs one of the matrix-matrix operations ! ! C := alpha*A * B + beta*C, ! ! or ! ! C := alpha * B*A + beta*C, ! ! where alpha and beta are scalars, A is an hermitian matrix and B and ! C are m by n matrices. ! ! Parameters: ! ! SIDE - character. ! On entry, SIDE specifies whether the hermitian matrix A ! appears on the left or right in the operation as follows: ! ! SIDE = 'L' or 'l' C := alpha*A * b + beta*C, ! ! SIDE = 'R' or 'r' C := alpha * b*A + beta*C, ! ! Unchanged on exit. ! ! UPLO - character. ! On entry, UPLO specifies whether the upper or lower ! triangular part of the hermitian matrix A is to be ! referenced as follows: ! ! UPLO = 'U' or 'u' Only the upper triangular part of the ! hermitian matrix is to be referenced. ! ! UPLO = 'L' or 'l' Only the lower triangular part of the ! hermitian matrix is to be referenced. ! ! Unchanged on exit. ! ! M - integer. ! On entry, M specifies the number of rows of the matrix C. ! M must be at least zero. ! Unchanged on exit. ! ! N - integer. ! On entry, N specifies the number of columns of the matrix C. ! N must be at least zero. ! Unchanged on exit. ! ! ALPHA - complex . ! On entry, ALPHA specifies the scalar alpha. ! Unchanged on exit. ! ! A - complex array of DIMENSION ( LDA, ka ), where ka is ! m when SIDE = 'L' or 'l' and is n otherwise. ! Before entry with SIDE = 'L' or 'l', the m by m part of ! the array A must contain the hermitian matrix, such that ! when UPLO = 'U' or 'u', the leading m by m upper triangular ! part of the array A must contain the upper triangular part ! of the hermitian matrix and the strictly lower triangular ! part of A is not referenced, and when UPLO = 'L' or 'l', ! the leading m by m lower triangular part of the array A ! must contain the lower triangular part of the hermitian ! matrix and the strictly upper triangular part of A is not ! referenced. ! Before entry with SIDE = 'R' or 'r', the n by n part of ! the array A must contain the hermitian matrix, such that ! when UPLO = 'U' or 'u', the leading n by n upper triangular ! part of the array A must contain the upper triangular part ! of the hermitian matrix and the strictly lower triangular ! part of A is not referenced, and when UPLO = 'L' or 'l', ! the leading n by n lower triangular part of the array A ! must contain the lower triangular part of the hermitian ! matrix and the strictly upper triangular part of A is not ! referenced. ! Note that the imaginary parts of the diagonal elements need ! not be set, they are assumed to be zero. ! Unchanged on exit. ! ! LDA - 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 ), otherwise LDA must be at ! least max( 1, n ). ! Unchanged on exit. ! ! B - complex array of DIMENSION ( LDB, n ). ! Before entry, the leading m by n part of the array B must ! contain the matrix B. ! Unchanged on exit. ! ! LDB - 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 ). ! Unchanged on exit. ! ! BETA - complex . ! On entry, BETA specifies the scalar beta. When BETA is ! supplied as zero then C need not be set on input. ! Unchanged on exit. ! ! C - complex array of DIMENSION ( LDC, n ). ! Before entry, the leading m by n part of the array C must ! contain the matrix C, except when beta is zero, in which ! case C need not be set on entry. ! On exit, the array C is overwritten by the m by n updated ! matrix. ! ! LDC - integer. ! On entry, LDC specifies the first dimension of C as declared ! in the calling (sub) program. LDC must be at least ! max( 1, m ). ! Unchanged on exit. ! implicit none integer lda integer ldb integer ldc integer m integer n character side character uplo complex alpha, beta complex a( lda, * ), b( ldb, * ), c( ldc, * ) logical lsame logical upper integer i, info, j, k, nrowa complex temp1, temp2 complex, parameter :: one = ( 1.0E+00, 0.0E+00 ) complex, parameter :: zero = ( 0.0E+00, 0.0E+00 ) ! ! Set NROWA as the number of rows of A. ! if ( lsame ( side, 'L' ) ) then nrowa = m else nrowa = n end if upper = lsame ( uplo, 'U' ) ! ! Test the input. ! info = 0 if ( ( .not.lsame ( side, 'L' ) ) .and. & ( .not.lsame ( side, 'R' ) ) ) then info = 1 else if ( ( .not.upper ) .and. & ( .not.lsame ( uplo, 'L' ) ) ) then info = 2 else if ( m <0 ) then info = 3 else if ( n <0 ) then info = 4 else if ( lda