rhapysody
Most simple solution is to use a Data Step to get what you want.
You seem to be interested to understand FCMP functionality. So, I pass my little knowledge on FCMP to you! A FCMP function or Subroutine consists of Data Step statements. Few matrix functions exclusively belong to FCMP Environment. One big advantage is that we can hold a Data Set as a two-dimensional Array (Matrix) in memory. Data staying in memory reduces I/O cost. I am giving a function later that reads a Data Set, holds in memory, manipulates cells. Then I write out the resulting Array as a Data Set.
For SAS programmers: As long as you keep the source code of the function in safe place, you need not worry about how it is saved as compiled code. There is no secrecy or threat. It requires user-familiarity.
Your OUTPUT shows adding of columns of theta.
The simplest way is to pass a _temporary_ array from the Data Step with values of theta and an another empty array to hold to-be-summed values in FCMP. I filled the theta: values to t[]. I created empty trans[] to pass to a Subroutine.
First the Subroutine ADD is made to receive two arrays t[] and tr[]. Addition is made using t[] and the sum is assigned to tr[]. The use of OUTARGS shares the arrays both in FCMP Environment and Data Step.
Before calling the Subroutine in the Data Step you tell the location where the compiled one is saved by:
options cmplib = work.func;
In the Data Step, read theta: and save to the _temporary_ array t[]. Create trans[] as a _temporary_ array.
You call the Subroutine Add, passing the two arrays.
Then copy the values from trans[] to tran[] array which writes out to WANT.
data have;
input theta1-theta3;
datalines;
0.2 0.5 0
0.3 0.6 0.023
0.5 0.1 0.05
0.7 0.2 0.01
;
run;
proc fcmp outlib = work.func.arr;
subroutine add(t[*], tr[*]);
outargs t, tr;
tr[1] = t[1];
do i = 2 to dim(t);
tr[i] = t[i-1] + t[i];
end;
endsub;
quit;
options cmplib = work.func;
data want;
array t[3] _temporary_;
array trans[3] _temporary_;
set have;
array th theta1-theta3;
do i = 1 to dim(t);
t[i] = th[i];
end;
call add(t,trans);
array tran trans1-trans3;
do i = 1 to dim(t);
tran[i] = trans[i];
end;
drop i th:;
run;
The Output:
Obs trans1 trans2 trans3
1 0.2 0.7 0.500
2 0.3 0.9 0.623
3 0.5 0.6 0.150
4 0.7 0.9 0.210
A better way is to just pass the Data Set (HAVE) to a FCMP function which reads the Data Set to a Dynamic Array and after additions are done in all rows, write out the Dynamic Array as a Data Set. Though your problem does not need this approach but you can use this example to try bigger problems later on.
I have given explanations for most of the statements as COMMENT in the following FCMP Function, DYNAMIC_ADD(). You are welcome to ask any doubts in the code.
proc fcmp outlib = work.myfunc.lib;
function dynamic_add(ds $);
file log;
array theta[1] / nosymbols; *Array head for THETA;
array trans[1] / nosymbols; *array head for TRANS;
rc = read_array('have', theta); *Dynamically sizes THETA and stores HAVE in a Matrix;
put theta =; * See the row-col values of HAVE;
rows = dim1(theta); cols = dim2(theta); * gets rows and cols of Matrix;
call dynamic_array(trans, rows, cols); * Create a Dynamic Array(TRANS) just like THETA;
do i = 1 to rows;
do j = 1 to cols - 1;
trans[i,1] = theta[i,1]; * First cell is copied;
trans[i,j+1] = theta[i, j+1] + theta[i, j]; * Here comes your calculations;
end;
end;
rc = write_array('WANTDYN', trans); * Write Out TRANS as a Data Set, WANTDYN;
return(1); * A Function needs a return statement and a dummy value is returned;/*EDITED*/
endsub;
quit;
options cmplib = work.myfunc; /*EDITED*/
data _null_;
rc = dynamic_add('have');
run;
proc print data = wantdyn;
run;
You simply need one statement in the Data Step. The FCMP Function writes out the Data Set as WANTDYN which gives the same OUTPUT as shown earlier.
Best regards,
DATAsp
... View more