## Should the GRAYCODE function return a row vector in IML?

I have been experimenting with the GRAYCODE function within an IML program and thought I would post my experiences for the benefit of others.

I was expecting to be able to define a vector x = j(1, 4, 0), set k = -1 and then call

rc = graycode(k, x);

in a loop, where x would cycle through all the combinations (effectively a representation of the binary numbers 0 to 15 in a minimum change order).  If I do that, I get an unhelpful error insisting that the first argument k should be binary, I think I can see now why I get this, but not the first few times.  It seems the only way to use it, is to provide a list of scalars that have all been pre-initialised.  So the following does work:

k = -1;
a = 0; b = 0; c = 0; d = 0;
do i=1 to 2##4;
rc = graycode(k, a, b, c, d);
print i k a b c d rc;
end;

the only problem is that I am thinking of putting this in an algorithm with 2^19 iterations, and managing 19 scalars is cumbersome to say the least.  Wouldn't it make much more sense to get the scalars returned as a row vector?  My solution is to create the row vector myself using the return codes, and just feed in zeros rather than scalars. This is far from intuitive, but does do what I want.

k = 0;
x = j(1, 4, 0);
rc = 0;
print x rc;
do i=2 to 2##4;
rc = graycode(k, 0, 0, 0, 0);

x[rc] = 1 - x[rc];
print x rc;
end;

I also tried  rc = graycode(k, , , , ) but regretted it!

1 ACCEPTED SOLUTION

Accepted Solutions

## Re: Should the GRAYCODE function return a row vector in IML?

I understand your frustration. I have blogged about the problem of calling Base SAS functions that require a list of parameters, and have provided a method that I often use to handle INPUT parameters: Calling Base SAS functions from SAS/IML: How to handle argument lists? - The DO Loop

In this case, the Base SAS function is providing multiple OUTPUT parameters, so you can't use my trick. However, you can solve your problem by using the CALL GRAYCODE subroutine rather than the GRAYCODE function.  It's not clear from your description whether you need a numerical vector or whether a character string will suffice. In the following statements, s is a character string; if you need a numerical vector, use the new functionality of the SUBSTR function to convert the string to a vector:

s='0000';

n=length(s);

k=countc(s, '0');

do i=2 to 2##n;

call graycode(k, s, n, '01');

x = num(substr(s, 1:n, 1));  /* necessary */

print i  k s x;

end;

BTW, when the initial string has 19 characters (s='0000000000000000000';) the program completes in less than a second, so it appears to be sufficiently efficient.

2 REPLIES 2

## Re: Should the GRAYCODE function return a row vector in IML?

I understand your frustration. I have blogged about the problem of calling Base SAS functions that require a list of parameters, and have provided a method that I often use to handle INPUT parameters: Calling Base SAS functions from SAS/IML: How to handle argument lists? - The DO Loop

In this case, the Base SAS function is providing multiple OUTPUT parameters, so you can't use my trick. However, you can solve your problem by using the CALL GRAYCODE subroutine rather than the GRAYCODE function.  It's not clear from your description whether you need a numerical vector or whether a character string will suffice. In the following statements, s is a character string; if you need a numerical vector, use the new functionality of the SUBSTR function to convert the string to a vector:

s='0000';

n=length(s);

k=countc(s, '0');

do i=2 to 2##n;

call graycode(k, s, n, '01');

x = num(substr(s, 1:n, 1));  /* necessary */

print i  k s x;

end;

BTW, when the initial string has 19 characters (s='0000000000000000000';) the program completes in less than a second, so it appears to be sufficiently efficient.

## Re: Should the GRAYCODE function return a row vector in IML?

Many thanks for your tips Rick.

From The DO Loop