Newsgroups: rec.arts.int-fiction,rec.games.int-fiction
Path: nntp.gmd.de!Dortmund.Germany.EU.net!main.Germany.EU.net!EU.net!www.nntp.primenet.com!nntp.primenet.com!netcom.com!erkyrath
From: erkyrath@netcom.com (Andrew Plotkin)
Subject: [Z-machine] Divison and modulo (was: JZIP/XZIP Patches)
Message-ID: <erkyrathDy7w36.8t0@netcom.com>
Organization: NETCOM On-line Communication Services (408 261-4700 guest)
X-Newsreader: TIN [version 1.2 PL1]
References: <Pine.LNX.3.95.960920173018.5222G-100000@adamant.res.wpi.edu> <erkyrathDy1z30.MMD@netcom.com> <slrn548at1.ivk.mike@skaro.lawlib.wm.edu> <Pine.LNX.3.95.960922165609.1217A-100000@adamant.res.wpi.edu> <526n52$en@europa.frii.com>
Date: Tue, 24 Sep 1996 03:23:30 GMT
Lines: 74
Sender: erkyrath@netcom7.netcom.com
Xref: nntp.gmd.de rec.arts.int-fiction:16505 rec.games.int-fiction:17437

John Holder (jholder@frii.com) wrote:
> PATCH FOUR: Fixing the modulus behaviour in math.c for Jzip & Xzip
> ------------------------------------------------------------------
> (NOTE: I recommend this patch to all Jzip and Xzip users.)
> Also, Jzip and probably Xzip have a bug in math.c which will cause the
> microwave oven in "The Lurking Horror" to misbehave.  All that needs to 
> be done is to change the store_operand line in the remainder function 
> (line 105) to read:
>
>  store_operand ((short)a % (short)b);
>
> This has the effect of makeing the mod (remainder) function signed.

Wheep! Wheep! Wheep!

The Z-spec (0.2) says that both divison and modulo are *unsigned* 16-bit 
operations.

Furthermore, the expression (a % b), with a and b signed numbers, does 
not produce consistent results on all machines. Honest! If either a or b 
is negative, the remainder may be positive *or* negative. This is stated 
explicitly in the K&R C manual, and the C++ Annotated Reference Manual. 
(I don't have the ANSI C manual handy, but I'm sure it's the same.) (This 
is because the division instruction on different CPUs may be wired either 
way, and compiler authors are too lazy to worry about it. It's not a good 
reason, but it's the reason.)

If Lurking Horror assumes signed division, we have a problem.

(Has there been any discussion on the Z-machine mailing list about this? 
I can't get into GMD to check.)

--Z

Footnote for Inform programmers: 

For exactly this reason, I keep the following Inform code fragment
handy:

! Find num/denom, rounded towards zero. Works even if num is negative. 
! Do not use if denom is negative; instead, call safe_div(-num, -denom.)
[ safe_div num denom;
  if (num < 0)
    return -((-num) / denom);
  return num / denom;
];

! Find num%denom, always returning the nonnegative modulo, even if
! num is negative. Do not use if denom is negative.
[ safe_mod num denom;
  if (num < 0)
    return (denom-1) - ((-1-num) % denom);
  return num % denom;
];

That last one may look strange, but it gives an evenly-repeating pattern:

safe_mod(4,  4) = 0
safe_mod(3,  4) = 3
safe_mod(2,  4) = 2
safe_mod(1,  4) = 1
safe_mod(0,  4) = 0
safe_mod(-1, 4) = 3
safe_mod(-2, 4) = 2
safe_mod(-3, 4) = 1
safe_mod(-4, 4) = 0
safe_mod(-5, 4) = 3

--Z

-- 

"And Aholibamah bare Jeush, and Jaalam, and Korah: these were the
borogoves..."
