Pyrite | Level 9

## Outer product capability for dyadic functions in IML

I have written an IML module to compute a table created by the application of a dyadic function ( '+', '#', '/', etc.) applied to two numeric vectors.

``````start o_p( dyadic_fcn, x, y ) ;
/* purpose: compute outer product of vectors x, y by applying dyadic function
*
* parameters:
*    dyadic_fcn ::= quoted dyadic function, e.g., + - = ^= # ## < > , &cetera
*    x          ::= numeric scalar or vector
*    y          ::= numeric scalar or vector
*
* returns outer product of column vector x <dyadic function> row vector y
*
*  example:
*    a = 1 : 4 ; b = 1 : 5 ;
*
*    c = op( '/', a, b ) ;
*/

tmp_x = colvec( x ) ; n_row_x = nrow( tmp_x ) ;
tmp_y = rowvec( y ) ; n_col_y = ncol( tmp_y ) ;

x_mat = repeat( tmp_x, 1, n_col_y ) ;   y_mat = repeat( tmp_y, n_row_x, 1 ) ;

call execute( 'rslt = x_mat', dyadic_fcn, 'y_mat ;' ) ;

return rslt ;
finish o_p ;``````

For example,

``````x = 1 : 5 ;
y = 1 : 3 ;

z1 = o_p( '<', x, y ) ;
z2 = o_p( '+', x, y ) ;
z3 = o_p( '^=', x, y ) ;
z4 = o_p( '#', x, y ) ;

print x y, z1[ l="dyadic function =' '<'"] " " z2[l="dyadic function = '+'"] " " z3[l="dyadic function = '^='"] " " z4[l="dyadic function = '#'"] ;

z = o_p( '#', 1, { 2 3 4 5 } ) ;
print z ;
``````

produces the results

``````x 	  	y
1 	2 	3 	4 	5 	1 	2 	3
0 	1 	1 	  	2 	3 	4 	  	0 	1 	1 	  	1 	2 	3
0 	0 	1 	  	3 	4 	5 	  	1 	0 	1 	  	2 	4 	6
0 	0 	0 	  	4 	5 	6 	  	1 	1 	0 	  	3 	6 	9
0 	0 	0 	  	5 	6 	7 	  	1 	1 	1 	  	4 	8 	12
0 	0 	0 	  	6 	7 	8 	  	1 	1 	1 	  	5 	10 	15
z
2 	3 	4 	5``````

I have solved the problem using conformable matrices, but it would be nice if there were an IML function to perform the same task more efficiently. I also know that I can use the APPLY function, but I have to define the particular dyadic function for two arguments, and this is an inelegant and inefficient use of APPLY, IMHO. The statement

``  z = colvec( x ) * rowvec( y ) ;``

produces the same result as z = o_p( '#', x, y ) but this is the only case of a built-in IML outer product function that I know of. Is there any equivalent in IML for general dyadic functions?

1 ACCEPTED SOLUTION

Accepted Solutions
SAS Super FREQ

## Re: Outer product capability for dyadic functions in IML

Interesting. I haven't seen the term 'dyadic function' use like this before. Looks like your 'dyadic functions' are the pairwise scalar operators

D[i,j] = x[i] op y[j]

Although I almost always recommend IML functions over SAS macros, but this might be a case where a macro is simpler:

``````proc iml;
/* use macro instead of a function call */
%macro o_p(x, op, y);
(colvec(&x) &op repeat(rowvec(&y),nrow(&x)*ncol(&x)))
%mend;

x = 1 : 5 ;
y = 1 : 3 ;
w1 = %o_p(x, <, y );
w2 = %o_p(x, +, y );
w3 = %o_p(x, ^=, y );
w4 = %o_p(x, #, y );
print w1[r=x c=y l="dyadic function = '<'"],
w2[r=x c=y l="dyadic function = '+'"],
w3[r=x c=y l="dyadic function = '^='"],
w4[r=x c=y l="dyadic function = '#'"];
``````
SAS Super FREQ

## Re: Outer product capability for dyadic functions in IML

Interesting. I haven't seen the term 'dyadic function' use like this before. Looks like your 'dyadic functions' are the pairwise scalar operators

D[i,j] = x[i] op y[j]

Although I almost always recommend IML functions over SAS macros, but this might be a case where a macro is simpler:

``````proc iml;
/* use macro instead of a function call */
%macro o_p(x, op, y);
(colvec(&x) &op repeat(rowvec(&y),nrow(&x)*ncol(&x)))
%mend;

x = 1 : 5 ;
y = 1 : 3 ;
w1 = %o_p(x, <, y );
w2 = %o_p(x, +, y );
w3 = %o_p(x, ^=, y );
w4 = %o_p(x, #, y );
print w1[r=x c=y l="dyadic function = '<'"],
w2[r=x c=y l="dyadic function = '+'"],
w3[r=x c=y l="dyadic function = '^='"],
w4[r=x c=y l="dyadic function = '#'"];
``````
From The DO Loop