Something IBM did right (RT division of negatives).

Stan Switzer sjs at jcricket.ctt.bellcore.com
Fri Nov 4 01:56:28 AEST 1988


In article <2730 at hound.UUCP> rkl1 at hound.UUCP (K.LAUX) writes:
> 
> 	I'm suprized that noone has questioned the validity of shifting
> instead of dividing by (powers of) 2.
> 
> 	What about the difference between Logical and Arithmetic shifts?
> If you want to divide, then divide!  A lot of compilers are smart enough
> to implement the divide as a shift, but only where appropriate.
> 
> 	I *did* notice the condition of dividend being positive, but now
> you have to *guarantee* that it will always be positive.  Also, by
> implication, the dividend is a *signed* quantity.  You can get into
> trouble if it gets changed to an *unsigned* quantity (like when 16K isn't
> enough).

Well, I really hate to open this can of worms yet again, but in my
experience whenever (for integer i) "i%4" and "i>>2" differ, what you
REALLY want is what "i>>2" does anyway (assuming 2's complement).
Which is to say that you want the MODULUS operation rather than the
REMAINDER operation.  I have seen MANY cases where this is true, and
have NEVER seen a case where it was false.

The PC/RT implements / to truncate to smaller values and i%n to always
return a value (0..n-1) for positive "n" (dunno about negative "n").
This is a CLEAR win because now the compiler can ALWAYS optimize
divisions by powers of two into right shifts without fretting over the
sign of the quotient.

The only argument for the common (mis)behavior of / and % that holds
even one drip of water is that FORTRAN requires you to do it wrong.

Please, do not argue that integer -1/2 should be -1 so that the sign
is the same as -1.0/2.0 or because "by the laws of arithmetic" (-1)/2
equals -(1/2).  These are pointless arguments that have no useful
consequences as far as correct programs are concerned.

Anyone wishing to take up the other side of the argument must find an
example of an actual situation where having -1/2 yield -1 is useful.
(The example must yield cases where the quotient can be both positive
or negative, otherwise I can just add or subtract one to the result
and get the same effect).

I offer the following examples in favor of the the "modular"
interpretation: 

1) [0..3] represents [north, east, south, and west].  With the modular
% operator, "dir = (dir-1)%4" means "turn left".  I first came across
this in a program that drew Hilbert curves.

2) Bit extraction:  To get the n'th bit from the current (char) pointer
"p" (0 bit is low) use "bit = (p[i/BITSPERCHAR]>>(i%BITSPERCHAR)) & 1"
This comes up in rasterization code often enough.  The usual solution
is to jimmy it so that you avoid negative "i" (or just use >>3 and &7
instead).

3) Window calculations in protocol handling need to know the
difference between two numbers (mod window's range). You should be
able to do "(i-j)/winrng" but must instead do "(winrng+i-j)/winrng".
I came across this case in an X.25 handler.

Actual code.  Real programs.  

Granted, to write portable code in "C" one must assume the worst.  The
point is that division must yield the same result whether optimized to
a shift or not.  Since there is no harm in it, you might as well
define integer division so that it is equivalent to the result of the
shift when that optimization can be made.

You should never have to code "i>>3" when you mean "i/8".  You should
also never have to worry that a 45 cycle divide instruction is going
to be used so that in case the quotient is negative you'll get the
answer that someone thought you wanted instead of the one you probably
really want anyway, especially when a shift would have worked just as
well.

Stan Switzer  sjs at ctt.bellcore.com



More information about the Comp.lang.c mailing list