The same function is shown below, in an ugglier, but more precise manner. It has been expressed solely using elements of the Q ISA1, and all intermediate values have been declared.
uint32 udiv32( uint32, uint32 ); uint32 uadd32( uint32, uint32 ); Output = log2( Input ); // Task A log2( x ) = y where uint32 y; uint32 i; uint32 j; uint32 k; uint32 one = 1; uint32 two = 2; i = udiv32( x, two ); j = log2( i ); // Task B k = uadd32( j, one ); y = if (x > 1) then k else 0 fi; end;
When this program fragment is expanded, the log2 graph will be instantiated once to handle two different invocations: Once for the application labeled task A, and once for task B (the internal recursion). Conditional operators are inserted on the input and output streams, to select them properly for position 0 along dimension r (task A), and all other positions along r (task B). In order to identify the unique state associated with each level of recursion, the r dimension is added to the streams in the expanded log2 graph. The resulting ``flattened'' code, assuming one dimensional Input and Output streams, is shown below.
dimension d,r; uint32 Input.d; uint32 Output.d; uint32 x.d,r; uint32 y.d,r; uint32 i.d,r; uint32 j.d,r; uint32 k.d,r; uint32 h.d,r; uint32 one = 1; uint32 two = 2; uint32 udiv32( uint32, uint32 ); uint32 uadd32( uint32, uint32 ); Output = select.r( y, 0, 1, 1 ); // y @.r 0 x = if (#.d == 0) then Input else h fi; h = resample.r( i, 1, -1 ); // prev.r i i = udiv32( x, two ); j = resample.r( y, 1, 1 ); // next.r y k = uadd32( j, one ); y = if (x > 1) then k else 0 fi;