!
! Copyright (C) 2021, MaX CoE
! Distributed under the MIT License 
! (license terms are at http://opensource.org/licenses/MIT).
!
!--
!
! Auxiliary functions
!
! AF: OpenACC support is incomplete !!
!
!==================================================================
!==================================================================
! *DO NOT EDIT*: automatically generated from device_auxfunc.jf90
!==================================================================
!==================================================================
!
#include<devxlib_macros.h>
#include<devxlib_defs.h>
!
!=======================================
!
submodule (devxlib_auxfunc) devxlib_auxfunc_mat_upd

   implicit none

   contains
!
      module subroutine dp_devxlib_mat_upd_dMd_r2d(ndim1, ndim2, mat, v1,op1, v2,op2, scal)
         !
         ! performs: mat(i,j) = scal * op1(v1(i)) * mat(i,j) * op2(v2(j))
         ! op = 'N', 'R', 'C',       'RC'
         !       x   1/x  conjg(x)   conjg(1/x)
         implicit none
         !   
         integer,      intent(in)    :: ndim1,ndim2
         real(real64), intent(inout) DEV_ATTR :: mat(:,:)
         real(real64), intent(in)    DEV_ATTR :: v1(:)
         real(real64), intent(in)    DEV_ATTR :: v2(:)
         character(1), intent(in)    :: op1, op2
         real(real64), optional, intent(in)  :: scal
         integer :: i,j
         !   
         if (op1=="N".and.op2=="N") then
            if (present(scal)) then
!DEV_CUF kernel do(2)
       !DEV_OMP parallel do default(shared), private(i,j), collapse(2)
               do j = 1, ndim2
                  do i = 1, ndim1
                     mat(i,j) = scal * v1(i) * mat(i,j) * v2(j)
                  enddo
               enddo

            else
!DEV_CUF kernel do(2)
       !DEV_OMP parallel do default(shared), private(i,j), collapse(2)
               do j = 1, ndim2
                  do i = 1, ndim1
                     mat(i,j) = v1(i) * mat(i,j) * v2(j)
                  enddo
               enddo

            endif
         elseif (op1=="R".and.op2=="R") then
            if (present(scal)) then
!DEV_CUF kernel do(2)
       !DEV_OMP parallel do default(shared), private(i,j), collapse(2)
               do j = 1, ndim2
                  do i = 1, ndim1
                     mat(i,j) = scal / v1(i) * mat(i,j) / v2(j)
                  enddo
               enddo

            else
!DEV_CUF kernel do(2)
       !DEV_OMP parallel do default(shared), private(i,j), collapse(2)
               do j = 1, ndim2
                  do i = 1, ndim1
                     mat(i,j) = mat(i,j) /v1(i) / v2(j)
                  enddo
               enddo

            endif
         else
            call devxlib_error("dp_mat_upd_dMd_r2d","invalid op1/op2",10)
         endif
         !
      end subroutine dp_devxlib_mat_upd_dMd_r2d
      !
      module subroutine dp_devxlib_mat_upd_dMd_c2d(ndim1, ndim2, mat, v1,op1, v2,op2, scal)
         !
         ! performs: mat(i,j) = scal * op1(v1(i)) * mat(i,j) * op2(v2(j))
         ! op = 'N', 'R', 'C',       'RC'
         !       x   1/x  conjg(x)   conjg(1/x)
         implicit none
         !   
         integer,      intent(in)    :: ndim1,ndim2
         complex(real64), intent(inout) DEV_ATTR :: mat(:,:)
         complex(real64), intent(in)    DEV_ATTR :: v1(:)
         complex(real64), intent(in)    DEV_ATTR :: v2(:)
         character(1), intent(in)    :: op1, op2
         complex(real64), optional, intent(in)  :: scal
         integer :: i,j
         !   
         if (op1=="N".and.op2=="N") then
            if (present(scal)) then
!DEV_CUF kernel do(2)
       !DEV_OMP parallel do default(shared), private(i,j), collapse(2)
               do j = 1, ndim2
                  do i = 1, ndim1
                     mat(i,j) = scal * v1(i) * mat(i,j) * v2(j)
                  enddo
               enddo

            else
!DEV_CUF kernel do(2)
       !DEV_OMP parallel do default(shared), private(i,j), collapse(2)
               do j = 1, ndim2
                  do i = 1, ndim1
                     mat(i,j) = v1(i) * mat(i,j) * v2(j)
                  enddo
               enddo

            endif
         elseif (op1=="R".and.op2=="R") then
            if (present(scal)) then
!DEV_CUF kernel do(2)
       !DEV_OMP parallel do default(shared), private(i,j), collapse(2)
               do j = 1, ndim2
                  do i = 1, ndim1
                     mat(i,j) = scal / v1(i) * mat(i,j) / v2(j)
                  enddo
               enddo

            else
!DEV_CUF kernel do(2)
       !DEV_OMP parallel do default(shared), private(i,j), collapse(2)
               do j = 1, ndim2
                  do i = 1, ndim1
                     mat(i,j) = mat(i,j) /v1(i) / v2(j)
                  enddo
               enddo

            endif
         elseif (op1=="C".and.op2=="C") then
            if (present(scal)) then
!DEV_CUF kernel do(2)
       !DEV_OMP parallel do default(shared), private(i,j), collapse(2)
               do j = 1, ndim2
                  do i = 1, ndim1
                     mat(i,j) = scal * conjg(v1(i)) * mat(i,j) * conjg(v2(j))
                  enddo
               enddo

            else
!DEV_CUF kernel do(2)
       !DEV_OMP parallel do default(shared), private(i,j), collapse(2)
               do j = 1, ndim2
                  do i = 1, ndim1
                     mat(i,j) = conjg(v1(i)) * mat(i,j) * conjg(v2(j))
                  enddo
               enddo

            endif
         else
            call devxlib_error("dp_mat_upd_dMd_c2d","invalid op1/op2",10)
         endif
         !
      end subroutine dp_devxlib_mat_upd_dMd_c2d
      !
      module subroutine sp_devxlib_mat_upd_dMd_r2d(ndim1, ndim2, mat, v1,op1, v2,op2, scal)
         !
         ! performs: mat(i,j) = scal * op1(v1(i)) * mat(i,j) * op2(v2(j))
         ! op = 'N', 'R', 'C',       'RC'
         !       x   1/x  conjg(x)   conjg(1/x)
         implicit none
         !   
         integer,      intent(in)    :: ndim1,ndim2
         real(real32), intent(inout) DEV_ATTR :: mat(:,:)
         real(real32), intent(in)    DEV_ATTR :: v1(:)
         real(real32), intent(in)    DEV_ATTR :: v2(:)
         character(1), intent(in)    :: op1, op2
         real(real32), optional, intent(in)  :: scal
         integer :: i,j
         !   
         if (op1=="N".and.op2=="N") then
            if (present(scal)) then
!DEV_CUF kernel do(2)
       !DEV_OMP parallel do default(shared), private(i,j), collapse(2)
               do j = 1, ndim2
                  do i = 1, ndim1
                     mat(i,j) = scal * v1(i) * mat(i,j) * v2(j)
                  enddo
               enddo

            else
!DEV_CUF kernel do(2)
       !DEV_OMP parallel do default(shared), private(i,j), collapse(2)
               do j = 1, ndim2
                  do i = 1, ndim1
                     mat(i,j) = v1(i) * mat(i,j) * v2(j)
                  enddo
               enddo

            endif
         elseif (op1=="R".and.op2=="R") then
            if (present(scal)) then
!DEV_CUF kernel do(2)
       !DEV_OMP parallel do default(shared), private(i,j), collapse(2)
               do j = 1, ndim2
                  do i = 1, ndim1
                     mat(i,j) = scal / v1(i) * mat(i,j) / v2(j)
                  enddo
               enddo

            else
!DEV_CUF kernel do(2)
       !DEV_OMP parallel do default(shared), private(i,j), collapse(2)
               do j = 1, ndim2
                  do i = 1, ndim1
                     mat(i,j) = mat(i,j) /v1(i) / v2(j)
                  enddo
               enddo

            endif
         else
            call devxlib_error("sp_mat_upd_dMd_r2d","invalid op1/op2",10)
         endif
         !
      end subroutine sp_devxlib_mat_upd_dMd_r2d
      !
      module subroutine sp_devxlib_mat_upd_dMd_c2d(ndim1, ndim2, mat, v1,op1, v2,op2, scal)
         !
         ! performs: mat(i,j) = scal * op1(v1(i)) * mat(i,j) * op2(v2(j))
         ! op = 'N', 'R', 'C',       'RC'
         !       x   1/x  conjg(x)   conjg(1/x)
         implicit none
         !   
         integer,      intent(in)    :: ndim1,ndim2
         complex(real32), intent(inout) DEV_ATTR :: mat(:,:)
         complex(real32), intent(in)    DEV_ATTR :: v1(:)
         complex(real32), intent(in)    DEV_ATTR :: v2(:)
         character(1), intent(in)    :: op1, op2
         complex(real32), optional, intent(in)  :: scal
         integer :: i,j
         !   
         if (op1=="N".and.op2=="N") then
            if (present(scal)) then
!DEV_CUF kernel do(2)
       !DEV_OMP parallel do default(shared), private(i,j), collapse(2)
               do j = 1, ndim2
                  do i = 1, ndim1
                     mat(i,j) = scal * v1(i) * mat(i,j) * v2(j)
                  enddo
               enddo

            else
!DEV_CUF kernel do(2)
       !DEV_OMP parallel do default(shared), private(i,j), collapse(2)
               do j = 1, ndim2
                  do i = 1, ndim1
                     mat(i,j) = v1(i) * mat(i,j) * v2(j)
                  enddo
               enddo

            endif
         elseif (op1=="R".and.op2=="R") then
            if (present(scal)) then
!DEV_CUF kernel do(2)
       !DEV_OMP parallel do default(shared), private(i,j), collapse(2)
               do j = 1, ndim2
                  do i = 1, ndim1
                     mat(i,j) = scal / v1(i) * mat(i,j) / v2(j)
                  enddo
               enddo

            else
!DEV_CUF kernel do(2)
       !DEV_OMP parallel do default(shared), private(i,j), collapse(2)
               do j = 1, ndim2
                  do i = 1, ndim1
                     mat(i,j) = mat(i,j) /v1(i) / v2(j)
                  enddo
               enddo

            endif
         elseif (op1=="C".and.op2=="C") then
            if (present(scal)) then
!DEV_CUF kernel do(2)
       !DEV_OMP parallel do default(shared), private(i,j), collapse(2)
               do j = 1, ndim2
                  do i = 1, ndim1
                     mat(i,j) = scal * conjg(v1(i)) * mat(i,j) * conjg(v2(j))
                  enddo
               enddo

            else
!DEV_CUF kernel do(2)
       !DEV_OMP parallel do default(shared), private(i,j), collapse(2)
               do j = 1, ndim2
                  do i = 1, ndim1
                     mat(i,j) = conjg(v1(i)) * mat(i,j) * conjg(v2(j))
                  enddo
               enddo

            endif
         else
            call devxlib_error("sp_mat_upd_dMd_c2d","invalid op1/op2",10)
         endif
         !
      end subroutine sp_devxlib_mat_upd_dMd_c2d
      !

end submodule devxlib_auxfunc_mat_upd