!
! This file is part of FBUF - Fortran BUFfers For Accelerators
! Copyright 2018 Pietro Bonfa'
! License: GPLv2
!
!--
!
!==================================================================
!==================================================================
! *DO NOT EDIT*: automatically generated from devxlib_buffers.jf90
!==================================================================
!==================================================================
!
#include<devxlib_macros.h>
#include<devxlib_defs.h>
!
!> The **Buffers** module.
!
module devxlib_buffer
  !
#if defined(__DXL_CUDAF)
  use cudafor
#elif defined(__DXL_OPENACC)
  use openacc
#elif defined(__DXL_OPENMP_GPU)
  use omp_lib
#endif
  use iso_fortran_env, only : real64

  implicit none
  !
  integer, parameter :: LLI = selected_int_kind(15)

  TYPE :: Node
#if defined(__DXL_CUDAF)
     BYTE, POINTER , device  :: space(:)
#else
     BYTE, POINTER                 :: space(:)
#endif
     LOGICAL             :: locked
     TYPE(Node), POINTER :: Next
  END TYPE Node
  !
  private
  !
  TYPE(Node), POINTER  :: Head => null()
  !
  public :: devxlib_buffer_t
  !

!> The main **fbuf** class.
  type :: devxlib_buffer_t
     logical :: verbose = .false.
     !
   contains
     procedure :: init                     !< Initialize the class selecting buffers dimension and number per type.\
     final :: clean

     procedure :: reinit
     procedure :: dealloc

     generic, public :: lock_buffer => &
                        lock_buffer_iv, &           !< Releases a integer vector buffer
                        lock_buffer_im, &           !< Releases a integer matrix buffer
                        lock_buffer_it, &           !< Releases a integer tensor buffer
                        lock_buffer_if, &           !< Releases a integer four_dimensional buffer
                        lock_buffer_rv, &           !< Releases a real(real64) vector buffer
                        lock_buffer_rm, &           !< Releases a real(real64) matrix buffer
                        lock_buffer_rt, &           !< Releases a real(real64) tensor buffer
                        lock_buffer_rf, &           !< Releases a real(real64) four_dimensional buffer
                        lock_buffer_cv, &           !< Releases a complex(real64) vector buffer
                        lock_buffer_cm, &           !< Releases a complex(real64) matrix buffer
                        lock_buffer_ct, &           !< Releases a complex(real64) tensor buffer
                        lock_buffer_cf           !< Releases a complex(real64) four_dimensional buffer
     !
     procedure, private :: lock_buffer_iv           !< Releases a integer vector buffer
     procedure, private :: lock_buffer_im           !< Releases a integer matrix buffer
     procedure, private :: lock_buffer_it           !< Releases a integer tensor buffer
     procedure, private :: lock_buffer_if           !< Releases a integer four_dimensional buffer
     procedure, private :: lock_buffer_rv           !< Releases a real(real64) vector buffer
     procedure, private :: lock_buffer_rm           !< Releases a real(real64) matrix buffer
     procedure, private :: lock_buffer_rt           !< Releases a real(real64) tensor buffer
     procedure, private :: lock_buffer_rf           !< Releases a real(real64) four_dimensional buffer
     procedure, private :: lock_buffer_cv           !< Releases a complex(real64) vector buffer
     procedure, private :: lock_buffer_cm           !< Releases a complex(real64) matrix buffer
     procedure, private :: lock_buffer_ct           !< Releases a complex(real64) tensor buffer
     procedure, private :: lock_buffer_cf           !< Releases a complex(real64) four_dimensional buffer
     !
     generic, public :: release_buffer => &
                        release_buffer_iv, &        !< Releases a integer vector buffer
                        release_buffer_im, &        !< Releases a integer matrix buffer
                        release_buffer_it, &        !< Releases a integer tensor buffer
                        release_buffer_if, &        !< Releases a integer four_dimensional buffer
                        release_buffer_rv, &        !< Releases a real(real64) vector buffer
                        release_buffer_rm, &        !< Releases a real(real64) matrix buffer
                        release_buffer_rt, &        !< Releases a real(real64) tensor buffer
                        release_buffer_rf, &        !< Releases a real(real64) four_dimensional buffer
                        release_buffer_cv, &        !< Releases a complex(real64) vector buffer
                        release_buffer_cm, &        !< Releases a complex(real64) matrix buffer
                        release_buffer_ct, &        !< Releases a complex(real64) tensor buffer
                        release_buffer_cf        !< Releases a complex(real64) four_dimensional buffer
     !
     procedure, private :: release_buffer_iv           !< Releases a integer vector buffer
     procedure, private :: release_buffer_im           !< Releases a integer matrix buffer
     procedure, private :: release_buffer_it           !< Releases a integer tensor buffer
     procedure, private :: release_buffer_if           !< Releases a integer four_dimensional buffer
     procedure, private :: release_buffer_rv           !< Releases a real(real64) vector buffer
     procedure, private :: release_buffer_rm           !< Releases a real(real64) matrix buffer
     procedure, private :: release_buffer_rt           !< Releases a real(real64) tensor buffer
     procedure, private :: release_buffer_rf           !< Releases a real(real64) four_dimensional buffer
     procedure, private :: release_buffer_cv           !< Releases a complex(real64) vector buffer
     procedure, private :: release_buffer_cm           !< Releases a complex(real64) matrix buffer
     procedure, private :: release_buffer_ct           !< Releases a complex(real64) tensor buffer
     procedure, private :: release_buffer_cf           !< Releases a complex(real64) four_dimensional buffer
     !
     generic, public :: prepare_buffer => &
                        prepare_buffer_iv, &        !< Releases a integer vector buffer
                        prepare_buffer_im, &        !< Releases a integer matrix buffer
                        prepare_buffer_it, &        !< Releases a integer tensor buffer
                        prepare_buffer_if, &        !< Releases a integer four_dimensional buffer
                        prepare_buffer_rv, &        !< Releases a real(real64) vector buffer
                        prepare_buffer_rm, &        !< Releases a real(real64) matrix buffer
                        prepare_buffer_rt, &        !< Releases a real(real64) tensor buffer
                        prepare_buffer_rf, &        !< Releases a real(real64) four_dimensional buffer
                        prepare_buffer_cv, &        !< Releases a complex(real64) vector buffer
                        prepare_buffer_cm, &        !< Releases a complex(real64) matrix buffer
                        prepare_buffer_ct, &        !< Releases a complex(real64) tensor buffer
                        prepare_buffer_cf        !< Releases a complex(real64) four_dimensional buffer
     !
     procedure, private :: prepare_buffer_iv           !< Releases a integer vector buffer
     procedure, private :: prepare_buffer_im           !< Releases a integer matrix buffer
     procedure, private :: prepare_buffer_it           !< Releases a integer tensor buffer
     procedure, private :: prepare_buffer_if           !< Releases a integer four_dimensional buffer
     procedure, private :: prepare_buffer_rv           !< Releases a real(real64) vector buffer
     procedure, private :: prepare_buffer_rm           !< Releases a real(real64) matrix buffer
     procedure, private :: prepare_buffer_rt           !< Releases a real(real64) tensor buffer
     procedure, private :: prepare_buffer_rf           !< Releases a real(real64) four_dimensional buffer
     procedure, private :: prepare_buffer_cv           !< Releases a complex(real64) vector buffer
     procedure, private :: prepare_buffer_cm           !< Releases a complex(real64) matrix buffer
     procedure, private :: prepare_buffer_ct           !< Releases a complex(real64) tensor buffer
     procedure, private :: prepare_buffer_cf           !< Releases a complex(real64) four_dimensional buffer
     !
     procedure, private :: lock_space
     procedure, private :: prepare_space
     procedure, private :: release_space
     procedure, public  :: dump_status
     procedure, public  :: print_report
  end type

  
  
contains
  !> Initialize the class selecting the device type.
  subroutine init(this, info, verbose)
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t),  intent(inout) :: this     !< The class.
    integer,       intent(out) :: info    !< Error reporting.
                                          !<  0: ok
                                          !< -1: generic error
    logical, optional, intent(in) :: verbose
    !
    this%verbose = .false.
    if (present(verbose)) this%verbose = verbose

    if (this%verbose) write (*, *) "[devxlib_buffer] Initializing buffers"
    NULLIFY (Head)
    info = 0
    !
  end subroutine init
  !
  subroutine clean(this)
    implicit none
    type(devxlib_buffer_t) :: this     !< The class.
    call this%dealloc()
  end subroutine clean
  !
  subroutine dealloc(this)
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t) :: this     !< The class.
    integer :: i, info
    TYPE(Node), POINTER  :: temp
#if defined(__DXL_OPENMP_GPU)
    integer(c_int) :: omp_device
    type(c_ptr)    :: cloc
#endif
    i = 0
    DO WHILE (ASSOCIATED(head))
#if defined (__DXL_CUDAF)

        IF ( ASSOCIATED(head%space) ) DEALLOCATE(head%space)

#elif defined(__DXL_OPENMP_GPU)

        omp_device = omp_get_default_device()
        IF ( ASSOCIATED(head%space) ) THEN
           cloc = c_loc(head%space(1))
           call omp_target_free(cloc, omp_device)
        ENDIF

#else
        IF ( ASSOCIATED(head%space) ) DEALLOCATE(head%space)
#endif
        temp => head
        head => head%next
        DEALLOCATE(temp)
        i = i + 1
    END DO
    NULLIFY (Head)
    if (this%verbose) write (*, '("[devxlib_buffer] Cleaned ", I2, " buffers")') i
  end subroutine dealloc
  !
  subroutine reinit(this, info)
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    integer, intent(out) :: info !< 0 -> ok ; -n -> failed, n buffers still allocated
    integer :: l
    TYPE(Node), POINTER  :: temp

    temp => Head
    l = 0
    DO WHILE (ASSOCIATED(temp))
        if (temp%locked) l = l + 1
        temp => temp%Next
    END DO
    IF ( l > 0 ) THEN
        info = -l
        return
    ELSE
        CALL this%dealloc()
        info = 0
    END IF
    !
  end subroutine reinit
  !
  subroutine dump_status(this)
    class(devxlib_buffer_t), intent(inout)     :: this     !< The class.
    TYPE(Node), POINTER  :: temp
    integer :: i
    i = 1
    temp => Head
    write (*, *) "Buffer status ================="
    write (*, *) "          n        size Locked"
    DO WHILE (ASSOCIATED(temp))
        write (*,'(I12, I12, L7)') i, SIZE(TemP%space, kind=LLI), TemP%locked
        TemP => TemP%Next
        i = i + 1
    END DO
    write (*, *) "-------------------------------"
  end subroutine dump_status
  !
  subroutine print_report(this, unit)
    class(devxlib_buffer_t), intent(inout)     :: this     !< The class.
    INTEGER, OPTIONAL, intent(in)          :: unit
    !
    TYPE(Node), POINTER  :: temp
    integer(kind=LLI) :: tsz
    integer :: i, l
    i = 0
    l = 0
    tsz = 0
    temp => Head
    DO WHILE (ASSOCIATED(temp))
        tsz = tsz + SIZE(temp%space, kind=LLI)
        if (temp%locked) l = l + 1
        temp => temp%Next
        i = i + 1
    END DO
    if ( present (unit) ) then
        write(unit,'("[devxlib_buffer] Currently allocated ",(es12.2)," Mbytes, locked: ",(I4)," /",(I4) )') &
              REAL(tsz)/1048576, l, i
    else
        write(*   ,'("[devxlib_buffer] Currently allocated ",(es12.2)," Mbytes, locked: ",(I4)," /",(I4) )') &
              REAL(tsz)/1048576, l, i
    end if
  end subroutine print_report
  !
  subroutine lock_space(this, d, cloc, info)
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)     :: this     !< The class.
    integer(kind=LLI), intent(in)          :: d
#if defined(__DXL_CUDAF)
    type(c_devptr), intent(inout)  :: cloc
#else
    type(c_ptr), intent(inout)             :: cloc
#endif
    integer, intent(out)                   :: info
#if defined(__DXL_OPENMP_GPU)
    integer(c_int)                         :: omp_device !< OpenMP default device
#endif
    !
    integer(kind=LLI) :: r, tsz, sz
    TYPE(Node), POINTER  :: temp, good
    INTEGER :: i, good_one_idx
    !
    r   = 0
    tsz = 0
    i   = 1
    !
    ! Find the smallest usable buffer
    good_one_idx = 0
    temp => Head
    NULLIFY(good)
    DO WHILE (ASSOCIATED(temp))
        sz = SIZE(TemP%space, kind=LLI)
        IF ( ( sz >= d ) .and. (TemP%locked .eqv. .false.) ) THEN
            IF ( good_one_idx >= 1 ) THEN
                IF ( sz - d < r) THEN
                    good => temp
                    r = SIZE(TemP%space, kind=LLI) - d
                    good_one_idx = i
                END IF
            ELSE
                good_one_idx = i
                good => temp
                r = sz - d
            END IF
            info = 0
        END IF
        !
        tsz = tsz + sz
        i = i + 1
        !
        TemP => TemP%Next
    END DO
    !
    ! Allocate a new buffer
    IF ( good_one_idx == 0 ) THEN
        ALLOCATE (good)
#if defined(__DXL_CUDAF)
        ALLOCATE (good%space(d), stat=info)
#elif defined(__DXL_OPENMP_GPU)
        omp_device = omp_get_default_device()
        cloc = omp_target_alloc(d, omp_device)
        IF (c_associated(cloc)) THEN
           CALL c_f_pointer( cloc, good%space, [ d ] )
           info = 0
        ELSE
           info = -10000
        ENDIF
#else
        ALLOCATE (good%space(d), stat=info)
#endif
        good%Next   => Head
        Head        => good
        tsz         = tsz + d
        if (this%verbose) write (*, '("[devxlib_buffer] Created new buffer")')
    ELSE
        if (this%verbose) write (*, '("[devxlib_buffer] Locked buffer", I4)') good_one_idx
    END IF
    !
    if (this%verbose) &
         write(*,'("[devxlib_buffer] Currently allocated ",(es12.2)," Mbytes")') &
             REAL(tsz)/1048576 ! 1024/1024
    !
    good%locked = .true.
#if defined(__DXL_CUDAF)
    cloc = c_devloc(good%space)
#elif defined(__DXL_OPENMP_GPU)
    cloc = c_loc(good%space(1))
#else
    cloc = c_loc(good%space(1))
#endif
    !
  end subroutine lock_space
  !
  subroutine prepare_space(this, d, info)
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)     :: this     !< The class.
    integer(kind=LLI), intent(in)          :: d
    integer, intent(out)                   :: info
    !
#if defined(__DXL_CUDAF)
    type(c_devptr) :: cloc
#elif defined(__DXL_OPENMP_GPU)
    type(c_ptr)    :: cloc
#endif
    integer(kind=LLI) :: r, tsz, sz
    TYPE(Node), POINTER  :: temp, good
    INTEGER :: i, good_one_idx
#if defined(__DXL_OPENMP_GPU)
    integer(c_int)                         :: omp_device !< OpenMP default device
#endif
    !
    r   = 0
    tsz = 0
    i   = 1
    !
    ! Find the smallest usable buffer
    good_one_idx = 0
    temp => Head
    NULLIFY(good)
    DO WHILE (ASSOCIATED(temp))
        sz = SIZE(TemP%space, kind=LLI)
        IF ( ( sz >= d ) .and. (TemP%locked .eqv. .false.) ) THEN
            good_one_idx = i
            info = 0
        END IF
        !
        tsz = tsz + sz
        i = i + 1
        !
        TemP => TemP%Next
    END DO
    !
    ! Allocate a new buffer if needed
    IF ( good_one_idx == 0 ) THEN
        ALLOCATE (good)
#if defined(__DXL_CUDAF)
        ALLOCATE (good%space(d), stat=info)
#elif defined(__DXL_OPENMP_GPU)
        omp_device = omp_get_default_device()
        cloc = omp_target_alloc(d, omp_device)
        CALL c_f_pointer( cloc, good%space, [ d ] )
#else
        ALLOCATE (good%space(d), stat=info)
#endif
        good%locked = .false.
        good%Next   => Head
        Head        => good
        tsz         = tsz + d
        if (this%verbose) write (*, '("[devxlib_buffer] Created new buffer")')
    ELSE
        if (this%verbose) write (*, '("[devxlib_buffer] Good buffer found: ", I4)') good_one_idx
    END IF
    !
    if (this%verbose) &
         write (*, '("[devxlib_buffer] Currently allocated ",(es12.2)," Mbytes")') &
              REAL(tsz)/1048576 ! 1024/1024
    !
  end subroutine prepare_space
  !
  subroutine release_space(this, cloc, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
#if defined(__DXL_CUDAF)
    type(c_devptr), intent(in) :: cloc
#else
    type(c_ptr), intent(in) :: cloc
#endif
    integer, intent(out)            :: info    
    !
    TYPE(Node), POINTER  :: temp
#if defined(__DXL_CUDAF)
    type(c_devptr) :: clocint
#else
    type(c_ptr)            :: clocint
#endif
    !
    integer :: i
    info = -1
    i = 1
    temp => head
    DO WHILE (ASSOCIATED(temp))
#if defined(__DXL_OPENMP_GPU)
        clocint = c_loc(TemP%space(1))
        IF ( C_ASSOCIATED(cloc, clocint) ) THEN
            TemP%locked=.false.
            info = 0
            EXIT
        END IF
#else
#if defined(__DXL_CUDAF)
        IF ( cloc == c_devloc(TemP%space) ) THEN
#else
        clocint = c_loc(TemP%space(1))
        IF ( C_ASSOCIATED(cloc, clocint) ) THEN
#endif
            TemP%locked=.false.
            info = 0
            EXIT
        END IF
#endif
        i = i + 1
        TemP => TemP%Next
    END DO
    if (this%verbose) write (*, '("[devxlib_buffer] Released buffer ", I4)') i
  end subroutine release_space
  !

  !> Get or allocate a buffer for an integer vector.
  subroutine lock_buffer_iv(this, p, vsize_, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    integer, pointer, intent(out) :: p(:)   !< Pointer possibly set to access buffer
    integer,       intent(in) :: vsize_   !< vector dimension
    integer,       intent(out) :: info    !<  0: ok
                                          !< -1: no buffers left, allocating space
                                          !< -2: unexpected error, no memory left
                                          !< other values come form allocate stat
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif
    integer(kind=LLI) :: d
#if defined(__DXL_CUDAF)
    type(c_devptr) :: cloc
#else
    type(c_ptr) :: cloc
#endif
    !
    integer :: dummy
    integer :: vsize(1)
    vsize(1) = vsize_
    !
    d = PRODUCT(vsize)
    d = d*SIZEOF(dummy)
    !
    ! Free and simple compatibility with zero dimension buffers.
    IF ( d == 0 ) d = 1
    !
    CALL this%lock_space(d, cloc, info)
    CALL c_f_pointer( cloc, p, vsize )

  end subroutine lock_buffer_iv

  !> Get or allocate a buffer for an integer matrix.
  subroutine lock_buffer_im(this, p, msize, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    integer, pointer, intent(out) :: p(:,:)   !< Pointer possibly set to access buffer
    integer,       intent(in) :: msize(2)   !< matrix dimension
    integer,       intent(out) :: info    !<  0: ok
                                          !< -1: no buffers left, allocating space
                                          !< -2: unexpected error, no memory left
                                          !< other values come form allocate stat
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif
    integer(kind=LLI) :: d
#if defined(__DXL_CUDAF)
    type(c_devptr) :: cloc
#else
    type(c_ptr) :: cloc
#endif
    !
    integer :: dummy
    !
    d = PRODUCT(msize)
    d = d*SIZEOF(dummy)
    !
    ! Free and simple compatibility with zero dimension buffers.
    IF ( d == 0 ) d = 1
    !
    CALL this%lock_space(d, cloc, info)
    CALL c_f_pointer( cloc, p, msize )

  end subroutine lock_buffer_im

  !> Get or allocate a buffer for an integer tensor.
  subroutine lock_buffer_it(this, p, tsize, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    integer, pointer, intent(out) :: p(:,:,:)   !< Pointer possibly set to access buffer
    integer,       intent(in) :: tsize(3)   !< tensor dimension
    integer,       intent(out) :: info    !<  0: ok
                                          !< -1: no buffers left, allocating space
                                          !< -2: unexpected error, no memory left
                                          !< other values come form allocate stat
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif
    integer(kind=LLI) :: d
#if defined(__DXL_CUDAF)
    type(c_devptr) :: cloc
#else
    type(c_ptr) :: cloc
#endif
    !
    integer :: dummy
    !
    d = PRODUCT(tsize)
    d = d*SIZEOF(dummy)
    !
    ! Free and simple compatibility with zero dimension buffers.
    IF ( d == 0 ) d = 1
    !
    CALL this%lock_space(d, cloc, info)
    CALL c_f_pointer( cloc, p, tsize )

  end subroutine lock_buffer_it

  !> Get or allocate a buffer for an integer four_dimensional.
  subroutine lock_buffer_if(this, p, fsize, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    integer, pointer, intent(out) :: p(:,:,:,:)   !< Pointer possibly set to access buffer
    integer,       intent(in) :: fsize(4)   !< four_dimensional dimension
    integer,       intent(out) :: info    !<  0: ok
                                          !< -1: no buffers left, allocating space
                                          !< -2: unexpected error, no memory left
                                          !< other values come form allocate stat
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif
    integer(kind=LLI) :: d
#if defined(__DXL_CUDAF)
    type(c_devptr) :: cloc
#else
    type(c_ptr) :: cloc
#endif
    !
    integer :: dummy
    !
    d = PRODUCT(fsize)
    d = d*SIZEOF(dummy)
    !
    ! Free and simple compatibility with zero dimension buffers.
    IF ( d == 0 ) d = 1
    !
    CALL this%lock_space(d, cloc, info)
    CALL c_f_pointer( cloc, p, fsize )

  end subroutine lock_buffer_if

  !> Get or allocate a buffer for an real(real64) vector.
  subroutine lock_buffer_rv(this, p, vsize_, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    real(real64), pointer, intent(out) :: p(:)   !< Pointer possibly set to access buffer
    integer,       intent(in) :: vsize_   !< vector dimension
    integer,       intent(out) :: info    !<  0: ok
                                          !< -1: no buffers left, allocating space
                                          !< -2: unexpected error, no memory left
                                          !< other values come form allocate stat
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif
    integer(kind=LLI) :: d
#if defined(__DXL_CUDAF)
    type(c_devptr) :: cloc
#else
    type(c_ptr) :: cloc
#endif
    !
    real(real64) :: dummy
    integer :: vsize(1)
    vsize(1) = vsize_
    !
    d = PRODUCT(vsize)
    d = d*SIZEOF(dummy)
    !
    ! Free and simple compatibility with zero dimension buffers.
    IF ( d == 0 ) d = 1
    !
    CALL this%lock_space(d, cloc, info)
    CALL c_f_pointer( cloc, p, vsize )

  end subroutine lock_buffer_rv

  !> Get or allocate a buffer for an real(real64) matrix.
  subroutine lock_buffer_rm(this, p, msize, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    real(real64), pointer, intent(out) :: p(:,:)   !< Pointer possibly set to access buffer
    integer,       intent(in) :: msize(2)   !< matrix dimension
    integer,       intent(out) :: info    !<  0: ok
                                          !< -1: no buffers left, allocating space
                                          !< -2: unexpected error, no memory left
                                          !< other values come form allocate stat
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif
    integer(kind=LLI) :: d
#if defined(__DXL_CUDAF)
    type(c_devptr) :: cloc
#else
    type(c_ptr) :: cloc
#endif
    !
    real(real64) :: dummy
    !
    d = PRODUCT(msize)
    d = d*SIZEOF(dummy)
    !
    ! Free and simple compatibility with zero dimension buffers.
    IF ( d == 0 ) d = 1
    !
    CALL this%lock_space(d, cloc, info)
    CALL c_f_pointer( cloc, p, msize )

  end subroutine lock_buffer_rm

  !> Get or allocate a buffer for an real(real64) tensor.
  subroutine lock_buffer_rt(this, p, tsize, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    real(real64), pointer, intent(out) :: p(:,:,:)   !< Pointer possibly set to access buffer
    integer,       intent(in) :: tsize(3)   !< tensor dimension
    integer,       intent(out) :: info    !<  0: ok
                                          !< -1: no buffers left, allocating space
                                          !< -2: unexpected error, no memory left
                                          !< other values come form allocate stat
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif
    integer(kind=LLI) :: d
#if defined(__DXL_CUDAF)
    type(c_devptr) :: cloc
#else
    type(c_ptr) :: cloc
#endif
    !
    real(real64) :: dummy
    !
    d = PRODUCT(tsize)
    d = d*SIZEOF(dummy)
    !
    ! Free and simple compatibility with zero dimension buffers.
    IF ( d == 0 ) d = 1
    !
    CALL this%lock_space(d, cloc, info)
    CALL c_f_pointer( cloc, p, tsize )

  end subroutine lock_buffer_rt

  !> Get or allocate a buffer for an real(real64) four_dimensional.
  subroutine lock_buffer_rf(this, p, fsize, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    real(real64), pointer, intent(out) :: p(:,:,:,:)   !< Pointer possibly set to access buffer
    integer,       intent(in) :: fsize(4)   !< four_dimensional dimension
    integer,       intent(out) :: info    !<  0: ok
                                          !< -1: no buffers left, allocating space
                                          !< -2: unexpected error, no memory left
                                          !< other values come form allocate stat
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif
    integer(kind=LLI) :: d
#if defined(__DXL_CUDAF)
    type(c_devptr) :: cloc
#else
    type(c_ptr) :: cloc
#endif
    !
    real(real64) :: dummy
    !
    d = PRODUCT(fsize)
    d = d*SIZEOF(dummy)
    !
    ! Free and simple compatibility with zero dimension buffers.
    IF ( d == 0 ) d = 1
    !
    CALL this%lock_space(d, cloc, info)
    CALL c_f_pointer( cloc, p, fsize )

  end subroutine lock_buffer_rf

  !> Get or allocate a buffer for an complex(real64) vector.
  subroutine lock_buffer_cv(this, p, vsize_, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    complex(real64), pointer, intent(out) :: p(:)   !< Pointer possibly set to access buffer
    integer,       intent(in) :: vsize_   !< vector dimension
    integer,       intent(out) :: info    !<  0: ok
                                          !< -1: no buffers left, allocating space
                                          !< -2: unexpected error, no memory left
                                          !< other values come form allocate stat
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif
    integer(kind=LLI) :: d
#if defined(__DXL_CUDAF)
    type(c_devptr) :: cloc
#else
    type(c_ptr) :: cloc
#endif
    !
    complex(real64) :: dummy
    integer :: vsize(1)
    vsize(1) = vsize_
    !
    d = PRODUCT(vsize)
    d = d*SIZEOF(dummy)
    !
    ! Free and simple compatibility with zero dimension buffers.
    IF ( d == 0 ) d = 1
    !
    CALL this%lock_space(d, cloc, info)
    CALL c_f_pointer( cloc, p, vsize )

  end subroutine lock_buffer_cv

  !> Get or allocate a buffer for an complex(real64) matrix.
  subroutine lock_buffer_cm(this, p, msize, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    complex(real64), pointer, intent(out) :: p(:,:)   !< Pointer possibly set to access buffer
    integer,       intent(in) :: msize(2)   !< matrix dimension
    integer,       intent(out) :: info    !<  0: ok
                                          !< -1: no buffers left, allocating space
                                          !< -2: unexpected error, no memory left
                                          !< other values come form allocate stat
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif
    integer(kind=LLI) :: d
#if defined(__DXL_CUDAF)
    type(c_devptr) :: cloc
#else
    type(c_ptr) :: cloc
#endif
    !
    complex(real64) :: dummy
    !
    d = PRODUCT(msize)
    d = d*SIZEOF(dummy)
    !
    ! Free and simple compatibility with zero dimension buffers.
    IF ( d == 0 ) d = 1
    !
    CALL this%lock_space(d, cloc, info)
    CALL c_f_pointer( cloc, p, msize )

  end subroutine lock_buffer_cm

  !> Get or allocate a buffer for an complex(real64) tensor.
  subroutine lock_buffer_ct(this, p, tsize, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    complex(real64), pointer, intent(out) :: p(:,:,:)   !< Pointer possibly set to access buffer
    integer,       intent(in) :: tsize(3)   !< tensor dimension
    integer,       intent(out) :: info    !<  0: ok
                                          !< -1: no buffers left, allocating space
                                          !< -2: unexpected error, no memory left
                                          !< other values come form allocate stat
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif
    integer(kind=LLI) :: d
#if defined(__DXL_CUDAF)
    type(c_devptr) :: cloc
#else
    type(c_ptr) :: cloc
#endif
    !
    complex(real64) :: dummy
    !
    d = PRODUCT(tsize)
    d = d*SIZEOF(dummy)
    !
    ! Free and simple compatibility with zero dimension buffers.
    IF ( d == 0 ) d = 1
    !
    CALL this%lock_space(d, cloc, info)
    CALL c_f_pointer( cloc, p, tsize )

  end subroutine lock_buffer_ct

  !> Get or allocate a buffer for an complex(real64) four_dimensional.
  subroutine lock_buffer_cf(this, p, fsize, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    complex(real64), pointer, intent(out) :: p(:,:,:,:)   !< Pointer possibly set to access buffer
    integer,       intent(in) :: fsize(4)   !< four_dimensional dimension
    integer,       intent(out) :: info    !<  0: ok
                                          !< -1: no buffers left, allocating space
                                          !< -2: unexpected error, no memory left
                                          !< other values come form allocate stat
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif
    integer(kind=LLI) :: d
#if defined(__DXL_CUDAF)
    type(c_devptr) :: cloc
#else
    type(c_ptr) :: cloc
#endif
    !
    complex(real64) :: dummy
    !
    d = PRODUCT(fsize)
    d = d*SIZEOF(dummy)
    !
    ! Free and simple compatibility with zero dimension buffers.
    IF ( d == 0 ) d = 1
    !
    CALL this%lock_space(d, cloc, info)
    CALL c_f_pointer( cloc, p, fsize )

  end subroutine lock_buffer_cf

  !

  !> Release the buffer corresponding to pointer p, if associated with a buffer. Otherwise just deallocates.
  subroutine release_buffer_iv(this, p, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    integer, pointer, intent(inout) :: p(:)   !< Pointer possibly pointing to buffer space
    integer, intent(out)            :: info
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif

#if defined(__DXL_CUDAF)

    CALL this%release_space(c_devloc(p), info)

#else
    CALL this%release_space(c_loc(p( lbound(p, 1))), info)
#endif
  end subroutine release_buffer_iv

  !> Release the buffer corresponding to pointer p, if associated with a buffer. Otherwise just deallocates.
  subroutine release_buffer_im(this, p, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    integer, pointer, intent(inout) :: p(:,:)   !< Pointer possibly pointing to buffer space
    integer, intent(out)            :: info
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif

#if defined(__DXL_CUDAF)

    CALL this%release_space(c_devloc(p), info)

#else
    CALL this%release_space(c_loc(p( lbound(p, 1),  lbound(p, 2))), info)
#endif
  end subroutine release_buffer_im

  !> Release the buffer corresponding to pointer p, if associated with a buffer. Otherwise just deallocates.
  subroutine release_buffer_it(this, p, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    integer, pointer, intent(inout) :: p(:,:,:)   !< Pointer possibly pointing to buffer space
    integer, intent(out)            :: info
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif

#if defined(__DXL_CUDAF)

    CALL this%release_space(c_devloc(p), info)

#else
    CALL this%release_space(c_loc(p( lbound(p, 1),  lbound(p, 2),  lbound(p, 3))), info)
#endif
  end subroutine release_buffer_it

  !> Release the buffer corresponding to pointer p, if associated with a buffer. Otherwise just deallocates.
  subroutine release_buffer_if(this, p, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    integer, pointer, intent(inout) :: p(:,:,:,:)   !< Pointer possibly pointing to buffer space
    integer, intent(out)            :: info
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif

#if defined(__DXL_CUDAF)

    CALL this%release_space(c_devloc(p), info)

#else
    CALL this%release_space(c_loc(p( lbound(p, 1),  lbound(p, 2),  lbound(p, 3),  lbound(p, 4))), info)
#endif
  end subroutine release_buffer_if

  !> Release the buffer corresponding to pointer p, if associated with a buffer. Otherwise just deallocates.
  subroutine release_buffer_rv(this, p, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    real(real64), pointer, intent(inout) :: p(:)   !< Pointer possibly pointing to buffer space
    integer, intent(out)            :: info
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif

#if defined(__DXL_CUDAF)

    CALL this%release_space(c_devloc(p), info)

#else
    CALL this%release_space(c_loc(p( lbound(p, 1))), info)
#endif
  end subroutine release_buffer_rv

  !> Release the buffer corresponding to pointer p, if associated with a buffer. Otherwise just deallocates.
  subroutine release_buffer_rm(this, p, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    real(real64), pointer, intent(inout) :: p(:,:)   !< Pointer possibly pointing to buffer space
    integer, intent(out)            :: info
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif

#if defined(__DXL_CUDAF)

    CALL this%release_space(c_devloc(p), info)

#else
    CALL this%release_space(c_loc(p( lbound(p, 1),  lbound(p, 2))), info)
#endif
  end subroutine release_buffer_rm

  !> Release the buffer corresponding to pointer p, if associated with a buffer. Otherwise just deallocates.
  subroutine release_buffer_rt(this, p, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    real(real64), pointer, intent(inout) :: p(:,:,:)   !< Pointer possibly pointing to buffer space
    integer, intent(out)            :: info
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif

#if defined(__DXL_CUDAF)

    CALL this%release_space(c_devloc(p), info)

#else
    CALL this%release_space(c_loc(p( lbound(p, 1),  lbound(p, 2),  lbound(p, 3))), info)
#endif
  end subroutine release_buffer_rt

  !> Release the buffer corresponding to pointer p, if associated with a buffer. Otherwise just deallocates.
  subroutine release_buffer_rf(this, p, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    real(real64), pointer, intent(inout) :: p(:,:,:,:)   !< Pointer possibly pointing to buffer space
    integer, intent(out)            :: info
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif

#if defined(__DXL_CUDAF)

    CALL this%release_space(c_devloc(p), info)

#else
    CALL this%release_space(c_loc(p( lbound(p, 1),  lbound(p, 2),  lbound(p, 3),  lbound(p, 4))), info)
#endif
  end subroutine release_buffer_rf

  !> Release the buffer corresponding to pointer p, if associated with a buffer. Otherwise just deallocates.
  subroutine release_buffer_cv(this, p, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    complex(real64), pointer, intent(inout) :: p(:)   !< Pointer possibly pointing to buffer space
    integer, intent(out)            :: info
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif

#if defined(__DXL_CUDAF)

    CALL this%release_space(c_devloc(p), info)

#else
    CALL this%release_space(c_loc(p( lbound(p, 1))), info)
#endif
  end subroutine release_buffer_cv

  !> Release the buffer corresponding to pointer p, if associated with a buffer. Otherwise just deallocates.
  subroutine release_buffer_cm(this, p, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    complex(real64), pointer, intent(inout) :: p(:,:)   !< Pointer possibly pointing to buffer space
    integer, intent(out)            :: info
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif

#if defined(__DXL_CUDAF)

    CALL this%release_space(c_devloc(p), info)

#else
    CALL this%release_space(c_loc(p( lbound(p, 1),  lbound(p, 2))), info)
#endif
  end subroutine release_buffer_cm

  !> Release the buffer corresponding to pointer p, if associated with a buffer. Otherwise just deallocates.
  subroutine release_buffer_ct(this, p, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    complex(real64), pointer, intent(inout) :: p(:,:,:)   !< Pointer possibly pointing to buffer space
    integer, intent(out)            :: info
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif

#if defined(__DXL_CUDAF)

    CALL this%release_space(c_devloc(p), info)

#else
    CALL this%release_space(c_loc(p( lbound(p, 1),  lbound(p, 2),  lbound(p, 3))), info)
#endif
  end subroutine release_buffer_ct

  !> Release the buffer corresponding to pointer p, if associated with a buffer. Otherwise just deallocates.
  subroutine release_buffer_cf(this, p, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    complex(real64), pointer, intent(inout) :: p(:,:,:,:)   !< Pointer possibly pointing to buffer space
    integer, intent(out)            :: info
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif

#if defined(__DXL_CUDAF)

    CALL this%release_space(c_devloc(p), info)

#else
    CALL this%release_space(c_loc(p( lbound(p, 1),  lbound(p, 2),  lbound(p, 3),  lbound(p, 4))), info)
#endif
  end subroutine release_buffer_cf

  !

  !> 
  subroutine prepare_buffer_iv(this, p, vsize_, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    integer, pointer, intent(out) :: p(:)   !< Pointer (only used for assesing type)
    integer,       intent(in) :: vsize_   !< vector dimension
    integer,       intent(out) :: info    !<  0: ok
                                          !< -1: no buffers left, allocating space
                                          !< -2: unexpected error, no memory left
                                          !< other values come form allocate stat
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif
    integer(kind=LLI) :: d
#if defined(__DXL_CUDAF)
    type(c_devptr) :: cloc
#else
    type(c_ptr) :: cloc
#endif
    !
    integer :: dummy
    integer :: vsize(1)
    vsize(1) = vsize_
    !
    d = PRODUCT(vsize)
    d = d*SIZEOF(dummy)
    !
    CALL this%prepare_space(d, info)
    !
  end subroutine prepare_buffer_iv

  !> 
  subroutine prepare_buffer_im(this, p, msize, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    integer, pointer, intent(out) :: p(:,:)   !< Pointer (only used for assesing type)
    integer,       intent(in) :: msize(2)   !< matrix dimension
    integer,       intent(out) :: info    !<  0: ok
                                          !< -1: no buffers left, allocating space
                                          !< -2: unexpected error, no memory left
                                          !< other values come form allocate stat
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif
    integer(kind=LLI) :: d
#if defined(__DXL_CUDAF)
    type(c_devptr) :: cloc
#else
    type(c_ptr) :: cloc
#endif
    !
    integer :: dummy
    !
    d = PRODUCT(msize)
    d = d*SIZEOF(dummy)
    !
    CALL this%prepare_space(d, info)
    !
  end subroutine prepare_buffer_im

  !> 
  subroutine prepare_buffer_it(this, p, tsize, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    integer, pointer, intent(out) :: p(:,:,:)   !< Pointer (only used for assesing type)
    integer,       intent(in) :: tsize(3)   !< tensor dimension
    integer,       intent(out) :: info    !<  0: ok
                                          !< -1: no buffers left, allocating space
                                          !< -2: unexpected error, no memory left
                                          !< other values come form allocate stat
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif
    integer(kind=LLI) :: d
#if defined(__DXL_CUDAF)
    type(c_devptr) :: cloc
#else
    type(c_ptr) :: cloc
#endif
    !
    integer :: dummy
    !
    d = PRODUCT(tsize)
    d = d*SIZEOF(dummy)
    !
    CALL this%prepare_space(d, info)
    !
  end subroutine prepare_buffer_it

  !> 
  subroutine prepare_buffer_if(this, p, fsize, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    integer, pointer, intent(out) :: p(:,:,:,:)   !< Pointer (only used for assesing type)
    integer,       intent(in) :: fsize(4)   !< four_dimensional dimension
    integer,       intent(out) :: info    !<  0: ok
                                          !< -1: no buffers left, allocating space
                                          !< -2: unexpected error, no memory left
                                          !< other values come form allocate stat
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif
    integer(kind=LLI) :: d
#if defined(__DXL_CUDAF)
    type(c_devptr) :: cloc
#else
    type(c_ptr) :: cloc
#endif
    !
    integer :: dummy
    !
    d = PRODUCT(fsize)
    d = d*SIZEOF(dummy)
    !
    CALL this%prepare_space(d, info)
    !
  end subroutine prepare_buffer_if

  !> 
  subroutine prepare_buffer_rv(this, p, vsize_, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    real(real64), pointer, intent(out) :: p(:)   !< Pointer (only used for assesing type)
    integer,       intent(in) :: vsize_   !< vector dimension
    integer,       intent(out) :: info    !<  0: ok
                                          !< -1: no buffers left, allocating space
                                          !< -2: unexpected error, no memory left
                                          !< other values come form allocate stat
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif
    integer(kind=LLI) :: d
#if defined(__DXL_CUDAF)
    type(c_devptr) :: cloc
#else
    type(c_ptr) :: cloc
#endif
    !
    real(real64) :: dummy
    integer :: vsize(1)
    vsize(1) = vsize_
    !
    d = PRODUCT(vsize)
    d = d*SIZEOF(dummy)
    !
    CALL this%prepare_space(d, info)
    !
  end subroutine prepare_buffer_rv

  !> 
  subroutine prepare_buffer_rm(this, p, msize, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    real(real64), pointer, intent(out) :: p(:,:)   !< Pointer (only used for assesing type)
    integer,       intent(in) :: msize(2)   !< matrix dimension
    integer,       intent(out) :: info    !<  0: ok
                                          !< -1: no buffers left, allocating space
                                          !< -2: unexpected error, no memory left
                                          !< other values come form allocate stat
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif
    integer(kind=LLI) :: d
#if defined(__DXL_CUDAF)
    type(c_devptr) :: cloc
#else
    type(c_ptr) :: cloc
#endif
    !
    real(real64) :: dummy
    !
    d = PRODUCT(msize)
    d = d*SIZEOF(dummy)
    !
    CALL this%prepare_space(d, info)
    !
  end subroutine prepare_buffer_rm

  !> 
  subroutine prepare_buffer_rt(this, p, tsize, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    real(real64), pointer, intent(out) :: p(:,:,:)   !< Pointer (only used for assesing type)
    integer,       intent(in) :: tsize(3)   !< tensor dimension
    integer,       intent(out) :: info    !<  0: ok
                                          !< -1: no buffers left, allocating space
                                          !< -2: unexpected error, no memory left
                                          !< other values come form allocate stat
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif
    integer(kind=LLI) :: d
#if defined(__DXL_CUDAF)
    type(c_devptr) :: cloc
#else
    type(c_ptr) :: cloc
#endif
    !
    real(real64) :: dummy
    !
    d = PRODUCT(tsize)
    d = d*SIZEOF(dummy)
    !
    CALL this%prepare_space(d, info)
    !
  end subroutine prepare_buffer_rt

  !> 
  subroutine prepare_buffer_rf(this, p, fsize, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    real(real64), pointer, intent(out) :: p(:,:,:,:)   !< Pointer (only used for assesing type)
    integer,       intent(in) :: fsize(4)   !< four_dimensional dimension
    integer,       intent(out) :: info    !<  0: ok
                                          !< -1: no buffers left, allocating space
                                          !< -2: unexpected error, no memory left
                                          !< other values come form allocate stat
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif
    integer(kind=LLI) :: d
#if defined(__DXL_CUDAF)
    type(c_devptr) :: cloc
#else
    type(c_ptr) :: cloc
#endif
    !
    real(real64) :: dummy
    !
    d = PRODUCT(fsize)
    d = d*SIZEOF(dummy)
    !
    CALL this%prepare_space(d, info)
    !
  end subroutine prepare_buffer_rf

  !> 
  subroutine prepare_buffer_cv(this, p, vsize_, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    complex(real64), pointer, intent(out) :: p(:)   !< Pointer (only used for assesing type)
    integer,       intent(in) :: vsize_   !< vector dimension
    integer,       intent(out) :: info    !<  0: ok
                                          !< -1: no buffers left, allocating space
                                          !< -2: unexpected error, no memory left
                                          !< other values come form allocate stat
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif
    integer(kind=LLI) :: d
#if defined(__DXL_CUDAF)
    type(c_devptr) :: cloc
#else
    type(c_ptr) :: cloc
#endif
    !
    complex(real64) :: dummy
    integer :: vsize(1)
    vsize(1) = vsize_
    !
    d = PRODUCT(vsize)
    d = d*SIZEOF(dummy)
    !
    CALL this%prepare_space(d, info)
    !
  end subroutine prepare_buffer_cv

  !> 
  subroutine prepare_buffer_cm(this, p, msize, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    complex(real64), pointer, intent(out) :: p(:,:)   !< Pointer (only used for assesing type)
    integer,       intent(in) :: msize(2)   !< matrix dimension
    integer,       intent(out) :: info    !<  0: ok
                                          !< -1: no buffers left, allocating space
                                          !< -2: unexpected error, no memory left
                                          !< other values come form allocate stat
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif
    integer(kind=LLI) :: d
#if defined(__DXL_CUDAF)
    type(c_devptr) :: cloc
#else
    type(c_ptr) :: cloc
#endif
    !
    complex(real64) :: dummy
    !
    d = PRODUCT(msize)
    d = d*SIZEOF(dummy)
    !
    CALL this%prepare_space(d, info)
    !
  end subroutine prepare_buffer_cm

  !> 
  subroutine prepare_buffer_ct(this, p, tsize, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    complex(real64), pointer, intent(out) :: p(:,:,:)   !< Pointer (only used for assesing type)
    integer,       intent(in) :: tsize(3)   !< tensor dimension
    integer,       intent(out) :: info    !<  0: ok
                                          !< -1: no buffers left, allocating space
                                          !< -2: unexpected error, no memory left
                                          !< other values come form allocate stat
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif
    integer(kind=LLI) :: d
#if defined(__DXL_CUDAF)
    type(c_devptr) :: cloc
#else
    type(c_ptr) :: cloc
#endif
    !
    complex(real64) :: dummy
    !
    d = PRODUCT(tsize)
    d = d*SIZEOF(dummy)
    !
    CALL this%prepare_space(d, info)
    !
  end subroutine prepare_buffer_ct

  !> 
  subroutine prepare_buffer_cf(this, p, fsize, info)
#if defined(__DXL_CUDAF)
    use cudafor
#endif
    use iso_c_binding
    implicit none
    class(devxlib_buffer_t), intent(inout)  :: this     !< The class.
    complex(real64), pointer, intent(out) :: p(:,:,:,:)   !< Pointer (only used for assesing type)
    integer,       intent(in) :: fsize(4)   !< four_dimensional dimension
    integer,       intent(out) :: info    !<  0: ok
                                          !< -1: no buffers left, allocating space
                                          !< -2: unexpected error, no memory left
                                          !< other values come form allocate stat
#if defined(__DXL_CUDAF)
    attributes(device) :: p
#endif
    integer(kind=LLI) :: d
#if defined(__DXL_CUDAF)
    type(c_devptr) :: cloc
#else
    type(c_ptr) :: cloc
#endif
    !
    complex(real64) :: dummy
    !
    d = PRODUCT(fsize)
    d = d*SIZEOF(dummy)
    !
    CALL this%prepare_space(d, info)
    !
  end subroutine prepare_buffer_cf


end module devxlib_buffer