!
! Copyright (C) 2022, MaX CoE
! Distributed under the MIT License 
! (license terms are at http://opensource.org/licenses/MIT).
!
!--
!
! Utility functions to perform device memory mapping from host memory
! using CUDA-Fortran, OpenACC or OpenMP Offload
!
!==================================================================
!==================================================================
! *DO NOT EDIT*: automatically generated from device_mapping.jf90
!==================================================================
!==================================================================
!
#include<devxlib_macros.h>
#include<devxlib_defs.h>
!
!=======================================
!
module devxlib_mapping

   use iso_fortran_env,     only : int32, int64, real32, real64
   use devxlib_environment, only : devxlib_error
#if defined __DXL_CUDAF
   use cudafor
#elif defined __DXL_OPENACC
   use openacc
#elif defined __DXL_OPENMP_GPU
   use iso_c_binding, only : c_loc
   use omp_lib,       only : omp_get_default_device, omp_target_is_present
#endif

   implicit none

   interface devxlib_map
      module procedure &
{%- for t in types %}
{%- set outer_loop = loop %}
{%- for p in kinds[t] %}
{%- set medium_loop = loop %}
{%- for d in range(1,dimensions+1,3) %}
{%- if (d+1)<=dimensions %}
{%- if (d+2)<=dimensions %}
         {{p.name}}_devxlib_mapping_map_{{t[0]|lower}}{{d}}d, {{p.name}}_devxlib_mapping_map_{{t[0]|lower}}{{d+1}}d, {{p.name}}_devxlib_mapping_map_{{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_mapping_map_{{t[0]|lower}}{{d}}d, {{p.name}}_devxlib_mapping_map_{{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_mapping_map_{{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_map

   interface devxlib_unmap
      module procedure &
{%- for t in types %}
{%- set outer_loop = loop %}
{%- for p in kinds[t] %}
{%- set medium_loop = loop %}
{%- for d in range(1,dimensions+1,3) %}
{%- if (d+1)<=dimensions %}
{%- if (d+2)<=dimensions %}
         {{p.name}}_devxlib_mapping_unmap_{{t[0]|lower}}{{d}}d, {{p.name}}_devxlib_mapping_unmap_{{t[0]|lower}}{{d+1}}d, {{p.name}}_devxlib_mapping_unmap_{{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_mapping_unmap_{{t[0]|lower}}{{d}}d, {{p.name}}_devxlib_mapping_unmap_{{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_mapping_unmap_{{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_unmap

   interface devxlib_mapped
      module procedure &
{%- for t in types %}
{%- set outer_loop = loop %}
{%- for p in kinds[t] %}
{%- set medium_loop = loop %}
{%- for d in range(1,dimensions+1,3) %}
{%- if (d+1)<=dimensions %}
{%- if (d+2)<=dimensions %}
         {{p.name}}_devxlib_mapping_mapped_{{t[0]|lower}}{{d}}d, {{p.name}}_devxlib_mapping_mapped_{{t[0]|lower}}{{d+1}}d, {{p.name}}_devxlib_mapping_mapped_{{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_mapping_mapped_{{t[0]|lower}}{{d}}d, {{p.name}}_devxlib_mapping_mapped_{{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_mapping_mapped_{{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_mapped



   interface
   {%- for t in types %}
   {%- for p in kinds[t] %}
   {%- for d in range(1,dimensions+1) %}
      module subroutine {{p.name}}_devxlib_mapping_map_{{t[0]|lower}}{{d}}d(array, {% for dd in range(d) -%}
                                            {{ "range%s"|format(dd+1) }}{% if not loop.last %}, &
                                            {% endif %}{% endfor %} )
         implicit none
         {{t}}({{p.val}}), allocatable DEV_ATTR, intent(inout) :: array({% for dd in range(d) %}:{% if not loop.last %}, {%- endif %}{% endfor %})
         integer, optional, intent(in) :: {% for dd in range(d) %} {{ "range%s(2)"|format(dd+1) }}{% if not loop.last %}, {%- endif %}{% endfor %}
      end subroutine {{p.name}}_devxlib_mapping_map_{{t[0]|lower}}{{d}}d
   {%- endfor %}
   {%- endfor %}
   {%- endfor %}
   endinterface

   interface
   {%- for t in types %}
   {%- for p in kinds[t] %}
   {%- for d in range(1,dimensions+1) %}
      module subroutine {{p.name}}_devxlib_mapping_unmap_{{t[0]|lower}}{{d}}d(array, ierr)
         implicit none
         {{t}}({{p.val}}), allocatable DEV_ATTR :: array({% for dd in range(d) %}:{% if not loop.last %}, {%- endif %}{% endfor %})
         integer, optional, intent(out) :: ierr
      end subroutine {{p.name}}_devxlib_mapping_unmap_{{t[0]|lower}}{{d}}d
   {%- endfor %}
   {%- endfor %}
   {%- endfor %}
   endinterface

   interface
   {%- for t in types %}
   {%- for p in kinds[t] %}
   {%- for d in range(1,dimensions+1) %}
      module function {{p.name}}_devxlib_mapping_mapped_{{t[0]|lower}}{{d}}d(array) result(res)
         implicit none
         logical :: res
#if defined __DXL_OPENMP_GPU
         {{t}}({{p.val}}), allocatable, target :: array({% for dd in range(d) %}:{% if not loop.last %}, {%- endif %}{% endfor %})
#else
         {{t}}({{p.val}}), allocatable DEV_ATTR :: array({% for dd in range(d) %}:{% if not loop.last %}, {%- endif %}{% endfor %})
#endif
      end function {{p.name}}_devxlib_mapping_mapped_{{t[0]|lower}}{{d}}d
   {%- endfor %}
   {%- endfor %}
   {%- endfor %}
   endinterface
endmodule devxlib_mapping
