When we write SAS functions and subroutines in PROC FCMP, we want to be able to use arrays as arguments. Luckily this is possible. However, it is not always clear how this happens and what is allowed. This post attempts to clear things up a bit. First, I will demonstrate a simple example of how to use an array as an argument in PROC FCMP. Next, I will demonstrate a few examples of common pitfalls, ie. what is not allowed.

A Subroutine with an Array as Argument

First, let us write and store a simple SAS subroutine, that takes an array as argument. I do this by specifying x[*] as in the parentheses after the subroutine name s. There are two ways we can work with arrays from a data step in PROC FCMP. We compute a quantity from the array, such as the sum of it’s element and return the sum. This leaves it untouched. Or we can modify the array itself. In the example below, we do the latter. Therefore, we must list x in an Outargs Statement.

In the example below, I simply swap the first and last element in the input array. When we modify an array, ie. list it in the Outargs Statement, the array is passed by reference. If not, it is passed by value. You can read about the difference between the thread Passing by Value Vs Passing by Reference at StackOverflow.

proc fcmp outlib=work.f.f;
   subroutine s (x [*]);
      outargs x;
 
      t = x [hbound(x)];
      x [hbound(x)] = x [lbound(x)];
      x [lbound(x)] = t;
 
   endsub;
quit;

Now, I can use the function in a Data Step. Run the code below and verify that the first and last element trades places.

options cmplib=(work.f);
 
data _null_;
   array x {10} (1:10);
   call s (x);
   put (x[*])(=);
run;

The Limitations of Dynamic_Array

Next, let us take a look at what we can not do. In the blog post PROC FCMP Vs. Data Step Array in SAS, I demonstrate that the size of an FCMP array is dynamic. This means that we can modify its size and dimensions with the Dynamic_Array Routine. This could lead one to believe that we can take a data step array in PROC FCMP, use Dynamic_Array on it and return it to the Data Step. However, SAS does not allow this. Dynamic_Array is for FCMP local arrays only.

This means that the below code is not valid.

proc fcmp outlib=work.f.f;
   subroutine s (x [*]);
      outargs x;
 
      call dynamic_array (x, 1, 100);
   endsub;
quit;

Passing a Variable Number of Arguments

A SAS array can be thought of as a grouping of variables or values. However, passing an array to a function or subroutine in PROC FCMP is not the same as passing a variable number of arguments. PROC FCMP actually lets us write functions and subroutines, that accept a variable number of arguments. This is done with the Varargs Option in the Subroutine or Function Statement like this.

proc fcmp outlib=work.f.f;
    subroutine summin (t, x[*]) varargs;
        outargs t;
        t = 0;
        do i = 1 to dim(x);
            t = t + x[i];
        end;
    endsub;
 
    call summin (t, 1, 2, 3);
    put t=;
run;

The code above executes just fine and returns the sum of the variable number of input arguments. However, this is limited within PROC FCMP. Consider the code below.

options cmplib=(work.f);
 
data _null_;
    call summin (t, 1, 2, 3);
    put t=;
run;

This yields an error. Consequently, we can not use FCMP functions or subroutines with a variable number of arguments in the data step. There is a workaround available though. It involves storing the input elements in an array and that as argument. You can read more in this SAS Usage Note.

Summary

In this post, we investigate how to use a SAS array as argument in PROC FCMP. We see that there is a difference between computing statistics from it and modifying the array. Furthermore, we learn about a few common misconceptions when dealing with arrays in PROC FCMP.

You can download the entire code from this post here.