Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

CLASS(*) swap function

Julian_H_
Beginner
610 Views

Hello,

I need to write a generic swap routine and I was able to find a solution but it is not the most elegant way. Maybe you have an idea which could lead me in the right direction.

SUBROUTINE swap(a, b)
    IMPLICIT NONE
    
    CLASS(*), INTENT(INOUT) :: a, b
    INTEGER(1) :: tmp_int1
    REAL(4) :: tmp_real4
    
    IF (SAME_TYPE_AS(a, b)) THEN
      SELECT TYPE (a)
        TYPE IS (INTEGER(1))
          SELECT TYPE (b)
            TYPE IS (INTEGER(1))
              tmp_int1 = a
              a = b
              b = tmp_int1
          END SELECT
        
        TYPE IS (REAL(4))
          SELECT TYPE (b)
           TYPE IS (REAL(4))
            tmp_real4 = a
            a = b
            b = tmp_real4
          END SELECT
        
      END SELECT
    ELSE
      ! error 
    END IF
  END SUBROUTINE swap

 

as you can see to implement this for a lot of types is not an elegant solution, but due to the restricition "error #8304: In an intrinsic assignment statement, variable shall not be a non-allocatable polymorphic." I have no idea to do it in a different more general way.

 

0 Kudos
3 Replies
Arjen_Markus
Honored Contributor I
610 Views

It may not be what you are looking for exactly, but I would go with a generic interface instead:

interface

interface swap
    module procedure swap_int1
    module procedure swap_real4
end interface swap

contains
subroutine swap_int1( a, b) 
    ...
end subroutine swap_int1
...
end module
   

This avoids a long if-block and leaves it to the compiler to select the right one. If you need to use polymorphic variables, you could use your original approach for those cases.

 

0 Kudos
Jacob_Williams
New Contributor II
610 Views

There just isn't any good way to do this in Fortran. You either have to duplicate a lot of code or use "include" files (which still require duplicating the interfaces). You also have to know all the kinds in advance (you can't write a routine that will work with all the kinds the compiler supports without some kind of preprocessing trickery). Hopefully the next Fortran standard will include some useful generics capability that will fix this, but I guess we'll have to see in several years (hopefully less than 10).

0 Kudos
Julian_H_
Beginner
610 Views

Arjen Markus wrote:

It may not be what you are looking for exactly, but I would go with a generic interface instead:

interface

interface swap
    module procedure swap_int1
    module procedure swap_real4
end interface swap

contains
subroutine swap_int1( a, b) 
    ...
end subroutine swap_int1
...
end module
   

This avoids a long if-block and leaves it to the compiler to select the right one. If you need to use polymorphic variables, you could use your original approach for those cases.

About this I also thought, but it is not that much more elegant and the subroutines which are calling swap are using also CLASS(*) and I think you would be not able to pass CLASS(*) to the defined interface. I guess I will just stick with my solution I have so far. Thank you all for your suggestions.

0 Kudos
Reply