How to define a function to do job according to the size of input arrays?

Dear all,

I have a question kind of like function overloading, kind of not exactly like so, and it not elemental function either. It is just that,
How to define a function to do job according to different size of input arrays?

For example, two functions AAA and BBB

function AAA(x)
real :: x(1), AAA
! something
end function AAA

function BBB(x)
real :: x(2), BBB
! something completely different from function AAA does.
end function BBB

Is it possible to define a function CCC which can automatically switch between AAA and BBB depending on the size of the input array x?

I mean I can do

function CCC(x)
real :: x(:), CCC
if (size(x)==1)  CCC=AAA(x)
if (size(x)==2)  CCC=BBB(x)
end function CCC

Or I can use select case instead of the if then else.

But is there better more high performance elegant way?

Thanks much in advance!

Overloading works on rank, type and kind of the arguments, so that won’t work in this case. If your functions AAA and BBB do more than a simple assignment, then worrying about the performance of whatever dispatching mechanism is futile: it will not be noticeable.

If you are looking for a different way to encode it, you might try this (sketch only):

function CCC(x)
    real :: x(:)
    type(function_pointer), dimension(:) :: pfunction  ! Filled and defined elsewhere

    CCC = pfunction(size(x))%function(x)

Missing bits and pieces: the definition of the derived type, filling the elements with pointers to AAA and BBB and possibly others, clipping the index into pfunction to valid values (min(size(x), size(pfunction)), say)

It is not likely to be faster than a simple chain of ifs or (I would prefer that) a select-case. But it is extendible without changing the implementation of CCC.

1 Like

By using two derived types, the overloading will work:

module Vec
type :: Vec1_t
  real :: x(1)
end type Vec1_t
type :: Vec2_t
  real :: x(2)
end type Vec2_t

interface Vec
    module interface AAA,BBB
 end interface

contains

function AAA(Vec1)
type (vec1_t) :: Vec1
real :: AAA
! something
end function AAA

function BBB(Vec2)
type (vec1_t) :: Vec2
real :: BBB
! something completely different from function AAA does.
end function BBB
end module Vec

You can put the two derived types with the corresponding functions in two different modules.

2 Likes

Yes, that is certainly a solution :slight_smile:

1 Like