!                                                                                                                                                         c
! 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 devxlib_auxfunc.jf90
!==================================================================
!==================================================================
!
#include<devxlib_macros.h>
#include<devxlib_defs.h>
!
!=======================================
!
module devxlib_auxfunc
   !
   use iso_fortran_env,     only : real32, real64
   use devxlib_async,       only : dxl_async_kind
   use devxlib_environment, only : devxlib_error
   !
#if defined __DXL_CUDAF
   use cudafor
#endif

   implicit none

   private :: dxl_async_kind

   interface devxlib_conjg_d
      module procedure &
{% set t='complex' %}
{%- for p in precision %}
{%- set outer_loop = loop %}
{%- for d in range(1,dimensions+1,3) %}
{%- if (d+1)<=dimensions %}
{%- if (d+2)<=dimensions %}
         {{p.name}}_devxlib_conjg_{{t[0]|lower}}{{d}}d, {{p.name}}_devxlib_conjg_{{t[0]|lower}}{{d+1}}d, {{p.name}}_devxlib_conjg_{{t[0]|lower}}{{d+2}}d{% if ((not loop.last) or (not outer_loop.last))%}, &{%- endif %}
{%- else %}
         {{p.name}}_devxlib_conjg_{{t[0]|lower}}{{d}}d, {{p.name}}_devxlib_conjg_{{t[0]|lower}}{{d+1}}d{% if ((not loop.last) or (not outer_loop.last))%}, &{%- endif %}
{%- endif %}
{%- else %}
         {{p.name}}_devxlib_conjg_{{t[0]|lower}}{{d}}d{% if ((not loop.last) or (not outer_loop.last))%}, &{%- endif %}
{%- endif %}
{%- endfor %}
{%- endfor %}
   endinterface devxlib_conjg_d


   interface devxlib_conjg_h
      module procedure &
{% set t='complex' %}
{%- for p in precision %}
{%- set outer_loop = loop %}
{%- for d in range(1,dimensions+1,3) %}
{%- if (d+1)<=dimensions %}
{%- if (d+2)<=dimensions %}
         {{p.name}}_devxlib_conjg_h_{{t[0]|lower}}{{d}}d, {{p.name}}_devxlib_conjg_h_{{t[0]|lower}}{{d+1}}d, {{p.name}}_devxlib_conjg_h_{{t[0]|lower}}{{d+2}}d{% if ((not loop.last) or (not outer_loop.last))%}, &{%- endif %}
{%- else %}
         {{p.name}}_devxlib_conjg_h_{{t[0]|lower}}{{d}}d, {{p.name}}_devxlib_conjg_h_{{t[0]|lower}}{{d+1}}d{% if ((not loop.last) or (not outer_loop.last))%}, &{%- endif %}
{%- endif %}
{%- else %}
         {{p.name}}_devxlib_conjg_h_{{t[0]|lower}}{{d}}d{% if ((not loop.last) or (not outer_loop.last))%}, &{%- endif %}
{%- endif %}
{%- endfor %}
{%- endfor %}
   endinterface devxlib_conjg_h


   interface devxlib_conjg_d_p
      module procedure &
{% set t='complex' %}
{%- for p in precision %}
{%- set outer_loop = loop %}
{%- for d in range(1,dimensions+1,3) %}
{%- if (d+1)<=dimensions %}
{%- if (d+2)<=dimensions %}
         {{p.name}}_devxlib_conjg_{{t[0]|lower}}{{d}}d_p, {{p.name}}_devxlib_conjg_{{t[0]|lower}}{{d+1}}d_p, {{p.name}}_devxlib_conjg_{{t[0]|lower}}{{d+2}}d_p{% if ((not loop.last) or (not outer_loop.last))%}, &{%- endif %}
{%- else %}
         {{p.name}}_devxlib_conjg_{{t[0]|lower}}{{d}}d_p, {{p.name}}_devxlib_conjg_{{t[0]|lower}}{{d+1}}d_p{% if ((not loop.last) or (not outer_loop.last))%}, &{%- endif %}
{%- endif %}
{%- else %}
         {{p.name}}_devxlib_conjg_{{t[0]|lower}}{{d}}d_p{% if ((not loop.last) or (not outer_loop.last))%}, &{%- endif %}
{%- endif %}
{%- endfor %}
{%- endfor %}
   endinterface devxlib_conjg_d_p

   interface devxlib_vec_upd_remap
      module procedure &
{% set d=1 %}
{%- for p in precision %}
{%- set outer_loop = loop %}
{%- for t in types %}
         {{p.name}}_devxlib_vec_upd_remap_{{t[0]|lower}}{{d}}d{% if ((not loop.last) or (not outer_loop.last))%}, &{%- endif %}
{%- endfor %}
{%- endfor %}
   endinterface devxlib_vec_upd_remap

   interface devxlib_vec_upd_v_remap_v
      module procedure &
{% set d=1 %}
{%- for p in precision %}
{%- set outer_loop = loop %}
{%- for t in types %}
         {{p.name}}_devxlib_vec_upd_v_remap_v_{{t[0]|lower}}{{d}}d, &
{%- endfor %}
{%- endfor %}
{% set d=1 %}
{% set t= "complex" %}
{%- for p in precision %}
         {{p.name}}_devxlib_vec_upd_v_remap_v_x_{{t[0]|lower}}{{d}}d{% if (not loop.last)%}, &{%- endif %}
{%- endfor %}
   endinterface devxlib_vec_upd_v_remap_v

   interface devxlib_mat_upd_dMd
      module procedure &
{% set d=2 %}
{%- for p in precision %}
{%- set outer_loop = loop %}
{%- for t in types %}
         {{p.name}}_devxlib_mat_upd_dMd_{{t[0]|lower}}{{d}}d{% if ((not loop.last) or (not outer_loop.last))%}, &{%- endif %}
{%- endfor %}
{%- endfor %}
   endinterface devxlib_mat_upd_dMd

   interface devxlib_mem_addscal
      module procedure &
{%- for t in types %}
{%- set outer_loop = loop %}
{%- for p in precision %}
{%- set medium_loop = loop %}
{%- for d in range(1,dimensions+1,3) %}
{%- if (d+1)<=dimensions %}
{%- if (d+2)<=dimensions %}
         {{p.name}}_devxlib_mem_addscal_{{t[0]|lower}}{{d}}d, {{p.name}}_devxlib_mem_addscal_{{t[0]|lower}}{{d+1}}d, {{p.name}}_devxlib_mem_addscal_{{t[0]|lower}}{{d+2}}d{% if ((not loop.last) or (not medium_loop.last) or (not outer_loop.last))%}, &{%- endif %}
{%- else %}
         {{p.name}}_devxlib_mem_addscal_{{t[0]|lower}}{{d}}d, {{p.name}}_devxlib_mem_addscal_{{t[0]|lower}}{{d+1}}d{% if ((not loop.last) or (not medium_loop.last) or (not outer_loop.last))%}, &{%- endif %}
{%- endif %}
{%- else %}
         {{p.name}}_devxlib_mem_addscal_{{t[0]|lower}}{{d}}d{% if ((not loop.last) or (not medium_loop.last) or (not outer_loop.last))%}, &{%- endif %}
{%- endif %}
{%- endfor %}
{%- endfor %}
{%- endfor %}
   endinterface devxlib_mem_addscal

   interface
{% set t='complex' %}
{%- for p in precision %}
{%- for d in range(1,dimensions+1) %}
      module subroutine {{p.name}}_devxlib_conjg_{{t[0]|lower}}{{d}}d(array_inout, async_id, &
                                        {% for dd in range(d) %}
                                        {{ "range%s"|format(dd+1) }}, {{ "lbound%s"|format(dd+1) }}{% if not loop.last %}, &
                                        {%- endif %}{% endfor %} )
         implicit none
         {{t}}({{p.val}}) DEV_ATTR, intent(inout) :: array_inout({% for dd in range(d) %}:{% if not loop.last %}, {%- endif %}{% endfor %})
         integer(kind=dxl_async_kind), optional, intent(in) :: async_id
         integer, optional, intent(in) :: {% for dd in range(d) %} {{ "range%s(2)"|format(dd+1) }}{% if not loop.last %}, {%- endif %}{% endfor %}
         integer, optional, intent(in) :: {% for dd in range(d) %} {{ "lbound%s"  |format(dd+1) }}{% if not loop.last %}, {%- endif %}{% endfor %}
      end subroutine {{p.name}}_devxlib_conjg_{{t[0]|lower}}{{d}}d
      !
{%- endfor %}
{%- endfor %}
   endinterface

   interface
{% set t='complex' %}
{%- for p in precision %}
{%- for d in range(1,dimensions+1) %}
      module subroutine {{p.name}}_devxlib_conjg_h_{{t[0]|lower}}{{d}}d(array_inout, async_id, &
                                     {% for dd in range(d) %}
                                     {{ "range%s"|format(dd+1) }}, {{ "lbound%s"|format(dd+1) }}{% if not loop.last %}, &
                                     {%- endif %}{% endfor %} )
         implicit none
         {{t}}({{p.val}}), intent(inout) :: array_inout({% for dd in range(d) %}:{% if not loop.last %}, {%- endif %}{% endfor %})
         integer(kind=dxl_async_kind), optional, intent(in) :: async_id
         integer, optional, intent(in) :: {% for dd in range(d) %} {{ "range%s(2)"|format(dd+1) }}{% if not loop.last %}, {%- endif %}{% endfor %}
         integer, optional, intent(in) :: {% for dd in range(d) %} {{ "lbound%s"  |format(dd+1) }}{% if not loop.last %}, {%- endif %}{% endfor %}
      end subroutine {{p.name}}_devxlib_conjg_h_{{t[0]|lower}}{{d}}d
      !
{%- endfor %}
{%- endfor %}
   endinterface

   interface
{% set t='complex' %}
{%- for p in precision %}
{%- for d in range(1,dimensions+1) %}
      module subroutine {{p.name}}_devxlib_conjg_{{t[0]|lower}}{{d}}d_p(ptr_inout, async_id, &
                                        {% for dd in range(d) %}
                                        {{ "range%s"|format(dd+1) }}, {{ "lbound%s"|format(dd+1) }}{% if not loop.last %}, &
                                        {%- endif %}{% endfor %} )
         implicit none
         {{t}}({{p.val}}), pointer, contiguous, intent(inout) DEV_ATTR :: ptr_inout({% for dd in range(d) %}:{% if not loop.last %}, {%- endif %}{% endfor %})
         integer(kind=dxl_async_kind), optional, intent(in) :: async_id
         integer, optional, intent(in) :: {% for dd in range(d) %} {{ "range%s(2)"|format(dd+1) }}{% if not loop.last %}, {%- endif %}{% endfor %}
         integer, optional, intent(in) :: {% for dd in range(d) %} {{ "lbound%s"  |format(dd+1) }}{% if not loop.last %}, {%- endif %}{% endfor %}
      end subroutine {{p.name}}_devxlib_conjg_{{t[0]|lower}}{{d}}d_p
      !
{%- endfor %}
{%- endfor %}
   endinterface

   interface
{% set d=1 %}
{%- for p in precision %}
{%- for t in types %}
       module subroutine {{p.name}}_devxlib_vec_upd_remap_{{t[0]|lower}}{{d}}d(ndim, vout, v1, map1, scal)
          implicit none
          integer,      intent(in)    :: ndim
          {{t}}({{p.val}}) DEV_ATTR, intent(inout) :: vout({% for dd in range(d) %}:{% if not loop.last %}, {%- endif %}{% endfor %}) 
          {{t}}({{p.val}}) DEV_ATTR, intent(in)    :: v1({% for dd in range(d) %}:{% if not loop.last %}, {%- endif %}{% endfor %}) 
          integer DEV_ATTR,      intent(in)    :: map1({% for dd in range(d) %}:{% if not loop.last %}, {%- endif %}{% endfor %}) 
          {{t}}({{p.val}}), optional, intent(in)   :: scal
       end subroutine {{p.name}}_devxlib_vec_upd_remap_{{t[0]|lower}}{{d}}d
       !
{%- endfor %}
{%- endfor %}
   end interface

   interface
{% set d=1 %}
{%- for p in precision %}
{%- for t in types %}
      module subroutine {{p.name}}_devxlib_vec_upd_v_remap_v_{{t[0]|lower}}{{d}}d(ndim, vout, v1, map1, v2, scal)
         implicit none
         integer,      intent(in)    :: ndim
         {{t}}({{p.val}}) DEV_ATTR, intent(inout) :: vout({% for dd in range(d) %}:{% if not loop.last %}, {%- endif %}{% endfor %})
         {{t}}({{p.val}}) DEV_ATTR, intent(in)    :: v1({% for dd in range(d) %}:{% if not loop.last %}, {%- endif %}{% endfor %})
         integer DEV_ATTR,      intent(in)    :: map1({% for dd in range(d) %}:{% if not loop.last %}, {%- endif %}{% endfor %})
         {{t}}({{p.val}}) DEV_ATTR, intent(in)    :: v2({% for dd in range(d) %}:{% if not loop.last %}, {%- endif %}{% endfor %})
         {{t}}({{p.val}}), optional, intent(in)   :: scal
      end subroutine {{p.name}}_devxlib_vec_upd_v_remap_v_{{t[0]|lower}}{{d}}d
      !
{%- endfor %}
{%- endfor %}

{% set d=1 %}
{% set t= "complex" %}
{%- for p in precision %}
      module subroutine {{p.name}}_devxlib_vec_upd_v_remap_v_x_{{t[0]|lower}}{{d}}d(ndim, vout, v1,op1, map1, v2,op2, scal)
         implicit none
         integer,      intent(in)    :: ndim
         {{t}}({{p.val}}), intent(inout) :: vout({% for dd in range(d) %}:{% if not loop.last %}, {%- endif %}{% endfor %})
         {{t}}({{p.val}}), intent(in)    :: v1({% for dd in range(d) %}:{% if not loop.last %}, {%- endif %}{% endfor %})
         integer,      intent(in)    :: map1({% for dd in range(d) %}:{% if not loop.last %}, {%- endif %}{% endfor %})
         {{t}}({{p.val}}), intent(in)    :: v2({% for dd in range(d) %}:{% if not loop.last %}, {%- endif %}{% endfor %})
         character(1), intent(in)    :: op1, op2
         {{t}}({{p.val}}), optional, intent(in)    :: scal
#if defined(__DXL_CUDAF)
         attributes(device) :: vout, v1, v2, map1
#endif
      end subroutine {{p.name}}_devxlib_vec_upd_v_remap_v_x_{{t[0]|lower}}{{d}}d
      !
{%- endfor %}
   end interface

   interface
{% set d=2 %}
{%- for p in precision %}
{%- for t in types %}
      module subroutine {{p.name}}_devxlib_mat_upd_dMd_{{t[0]|lower}}{{d}}d(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
         {{t}}({{p.val}}), intent(inout) DEV_ATTR :: mat(:,:)
         {{t}}({{p.val}}), intent(in)    DEV_ATTR :: v1(:)
         {{t}}({{p.val}}), intent(in)    DEV_ATTR :: v2(:)
         character(1), intent(in)    :: op1, op2 
         {{t}}({{p.val}}), optional, intent(in)  :: scal
      end subroutine {{p.name}}_devxlib_mat_upd_dMd_{{t[0]|lower}}{{d}}d
      !
{%- endfor %}
{%- endfor %}
   end interface

   interface
{%- for t in types %}
{%- for p in precision %}
{%- for d in range(1,dimensions+1) %}
      module subroutine {{p.name}}_devxlib_mem_addscal_{{t[0]|lower}}{{d}}d(array_out, array_in, scal, &
                                                  {% for dd in range(d) -%}
                                                  {{ "range%s"|format(dd+1) }}, {{ "lbound%s"|format(dd+1) }}{% if not loop.last %}, &
                                                  {% endif %}{% endfor %} )
          implicit none
          {{t}}({{p.val}}), intent(inout) :: array_out({% for dd in range(d) %}:{% if not loop.last %}, {%- endif %}{% endfor %})
          {{t}}({{p.val}}), intent(in)    :: array_in({% for dd in range(d) %}:{% if not loop.last %}, {%- endif %}{% endfor %})
          {{t}}({{p.val}}), optional, intent(in) :: scal
          integer, optional, intent(in) :: {% for dd in range(d) %} {{ "range%s(2)"|format(dd+1) }}{% if not loop.last %}, {%- endif %}{% endfor %}
          integer, optional, intent(in) :: {% for dd in range(d) %} {{ "lbound%s"|format(dd+1) }}{% if not loop.last %}, {%- endif %}{% endfor %}
#if defined(__DXL_CUDAF)
          attributes(device) :: array_out, array_in
#endif
      end subroutine {{p.name}}_devxlib_mem_addscal_{{t[0]|lower}}{{d}}d
      !
{%- endfor %}
{%- endfor %}
{%- endfor %}
   end interface

endmodule devxlib_auxfunc
