[sci.math] MOD in Modula-2 flawed

kent@xanth.cs.odu.edu (Kent Paul Dolan) (02/13/88)

In article <6413@j.cc.purdue.edu> ags@j.cc.purdue.edu.UUCP (Dave
Seaman) writes: 
>In article <8802101656.AA08424@decwrl.dec.com> fulton@navion.dec.com
(10-Feb-1988 0957) writes: 
[lots omitted]

>>        Then you have -1 MOD 7  =>  -1,  which does not equate to any of
>>        the numbers assigned to Sunday thru Saturday, namely 0 thru 6. 

>I don't have my copy of the Modula-2 standard available at the moment, but
>I believe that the definition of the MOD operator is similar to Pascal,
>where the standard says:
>
>	A term of the form i mod j shall be an error if j is zero or
>	negative, otherwise the value of i mod j shall be that value of
>	(i-(k*j)) for integral k such that 0 <= i mod j < j.
>
>Therefore the correct value of (-1 MOD 7) is 6, not -1.  In fact, I believe
>that in Modula-2 the result of the MOD operator is type CARDINAL and
>therefore cannot be negative.  It sounds as if you may be stuck with a
>flawed implementation of Modula-2.

Sadly, the flaw is in Wirth's design, not Logitech's implementation.
I don't have his 3rd Edition Modula-2 reference manual handy (it's out
on loan), but I read it through in January, and was incredulous that
he would chose an implementation of MOD that is negative or zero to
the left of the origin (in y = x MOD modulus coordinates) and positive
or zero to the right of the origin, but there it was in print.  I
quickly took out my copy of the BENCHMARK Modula-2 compiler for the
Amiga, and wrote my first program to test this design flaw.  The
program worked as the book explained.  Aaaaargh.

I have run into the same problem in other languages (FORTRAN IV for
the HP 1000 many years ago comes to mind), and the work-around is
always the same: y = ((x MOD modulus) + modulus) MOD modulus.  Gag!

It appears Wirth was too seduced by the beauty of the "identity" x =
modulus * ( x DIV modulus ) + ( x MOD modulus ) [which is how he
defines MOD] to notice that the resulting modulus function is flawed
for any normal use (Life games on a 0..n-1 by 0..n-1 toroid, where the
value of cell (0,0) depends on the value of "cell" (-1 MOD n,-1 MOD n)
= (n-1,n-1), for example, or array-implemented ring queues, where one
wants to be able to index backward past the queue's origin and still
stay within the queue).  Even the giants have feet of clay, I guess.

I have been unable to communicate this problem to Dr. Wirth, so if one
of the European readers knows a forwarding address, by all means send
this note along to him.

Kent, the man from xanth.

claudio@forty2.UUCP (Claudio Nieder) (02/17/88)

In article <4057@xanth.cs.odu.edu> kent@xanth.UUCP (Kent Paul Dolan) writes:
> ...
>It appears Wirth was too seduced by the beauty of the "identity" x =
>modulus * ( x DIV modulus ) + ( x MOD modulus ) [which is how he
>defines MOD]... 

I think the above mentioned "identity" is quite right, the problem is
how you define x DIV modulus. In PIM3 Wirth defines:

"Integer division is denoted by DIV and truncates the quotient. For
 example ... -15 DIV 4= -3"

but there seems some room for changes. On his compiler for the CERES
(a NS32032 based Workstation built at the ETH) he redefined that, thus
now 

 -15 DIV 4=-4 and -15 MOD 4=1

I have read in some paper that dealt with the proposed BSI Modula-2 standard
that Wirth suggested/considered/approved/wasn't against the following
solution (perhaps somebody who has acces to the BSI papers may tell more 
about that):

 -15 DIV 4=-4, -15 MOD 4=1
 -15  /  4=-3, -15 REM 4=-3

On CERES DIV, MOD and "/" are implemented as mentioned above while "REM"
is not implemented.

The way how you actually implement it may also be influenced by the underlying
Processor. On the NS32032 both definitions of DIV and MOD exist, thus it
is quite easy to provide both.

The MC68000 Processor provides only the "/",REM variant. Therefor on the
M2Amiga compiler, which implements both variants, "/" and REM simply use
the processors DIVS instruction while DIV and MOD generate more complex
code.


				claudio