2-18 Doz, Max, Min

The "doz" function is "difference or zero," defined as follows, for signed arguments:



It has been called "first grade subtraction," because the result is 0 if you try to take away too much. We will use it to implement max(x, y) and min(x, y). In this connection it is important to note that doz(x, y) can be negative; it is negative if the subtraction overflows. The difference or zero function can be used directly to implement the Fortran IDIM function, although in Fortran, results are generally undefined if overflow occurs.

There seems to be no very good way to implement doz(x, y), max(x, y), and min(x, y) in a branch-free way that is applicable to most computers. About the best we can do is to compute doz(x, y) using one of the expressions given on page 22 for the x < y predicate, and then compute max(x, y) and min(x, y) from it, as follows:



This computes doz(x, y) in seven instructions if the machine has equivalence, or eight if not, and it computes max(x, y) or min(x, y) in one more instruction.

The following are unsigned versions of these functions:



The IBM RISC/6000 computer, and its predecessor the 801, has doz(x, y) provided as a single instruction. It permits computing the max(x, y) and min(x, y) of signed integers in two instructions, and is occasionally useful in itself. Implementing max(x, y) and min(x, y) directly is more costly because the machine would then need paths from the output ports of the register file back to an input port, bypassing the ALU.

Machines that have conditional move can get destructive [2] max(x, y) and min(x, y) in two instructions. For example, on our full RISC, x max(x, y) can be calculated as follows (we write the target register first):

[2] A destructive operation is one that overwrites one or more of its arguments.

cmplt?z,x,y牋牋牋?Set z = 1 if x < y, else 0. 
movne?x,z,y牋牋牋?If z is nonzero, set x = y.