Some details about unintuitive behavior
Here are some "gotchas", places where the DAPPLE semantics
lead to surprising results:
-
In the
shift()
and rotate()
operations, all elements participate, regardless of the active set.
This effect may not always be obvious, because you always view the
resulting vector through the active set. That is, once you have
used shift()
on an input vector, and print the
result vector or assign the result vector to another vector, that
printing or assignment is active-set sensitive. For example,
intVector X(N), Y(N), Z(N);
...
ifp (Y == 0)
Y = shift(X, -1);
All zero elements of Y will be updated with a new value; they
receive the value from the corresponding position of a new vector,
formed as a result of shifting the entire vector X left
by one position (as opposed to shifting each active element of X
left one position in the active subset of X). Thus, in the above
example
if
Y is (0, 8, 6, 0, 7) initially
and
X is (1, 2, 3, 4, 5)
then
shift(X, -1) is (2, 3, 4, 5, 0)
and Y becomes (2, 8, 6, 5, 7)
- Mixing scalars and vectors of different types in an expression is
sometimes surprising. In C, multiplying an int and a float promotes
the int to a float before doing a floating-point multiply. In DAPPLE,
however, multiplying an intVector and a float scalar will cast the
scalar to an int before doing the intVector/int multiply, which is not
intuitive. The same happens for comparisons, etc. Fortunately, g++
with the -Wall option will warn you when this happens.
- Both branches of ifp() always execute. This is typical
data-parallel semantics, but can be surprising to the new data-parallel
programmer. For example:
boolean zero;
intVector X(N);
...
ifp (X == 0)
zero = true;
else
zero = false;
This will always set
zero
to true, then to false,
leaving it at false. The programmer probably wanted a reduction:
zero = all(x == 0);
-
break
or goto
inside of an ifp() does
not do what you expect:
intVector X(N);
...
while (...)
ifp (X == 0)
break;
else
...
Typical data-parallel semantics, which say that both the "then" and
"else" clauses get executed, make branching out of those clauses hard
to define. Unfortunately, I can't prevent it in DAPPLE. So, the
break will occur, but since ifp() is implemented as a loop, it breaks
out of the ifp() rather than out of the while(). This causes DAPPLE's
internal understanding of the context to be confused, and chaos
results.