Subject: bug in libc quad arithmetic for % operator
To: None <bostic@forge.BSDI.COM, tech-kern@NetBSD.ORG>
From: Chris Torek <torek@BSDI.COM>
List: tech-kern
Date: 10/09/1997 06:27:53
The NetBSD folks found this one; the fix is trivial. The quad
versions of / and % should produce the same results as the native
arithmetic, but quad `%' is broken.
A little test program shows the problem:
#include <err.h>
#include <stdlib.h>
int
main(argc, argv)
int argc;
char **argv;
{
long la, lb, lq, lr;
long long lla, llb, llq, llr;
if (argc < 3)
errx(1, "usage: mod x y");
la = strtol(argv[1], 0, 0);
lb = strtol(argv[2], 0, 0);
lq = la / lb;
lr = la % lb;
printf("long: %ld /%% %ld = %ld, %ld\n", la, lb, lq, lr);
lla = la;
llb = lb;
llq = lla / llb;
llr = lla % llb;
printf("ll: %lld /%% %lld = %lld, %lld\n", lla, llb, llq, llr);
return 0;
}
Run this with `7 5' and you get the expected (1, 2); with -7 5,
you get (-1, -2); but with 7 -5 you get (-1, 2) vs (-1, -2), and
with -7 -5 you get (1, -2) vs (1, 2). Clearly divdi3.c is okay
and moddi3.c is broken (although both are technically machine-
dependent). Here is the one-line fix...
Chris
Index: moddi3.c
===================================================================
RCS file: /master/lib/libc/quad/moddi3.c,v
retrieving revision 2.1
diff -c -2 -r2.1 moddi3.c
*** moddi3.c 1995/02/03 06:35:58 2.1
--- moddi3.c 1997/10/09 12:18:26
***************
*** 45,50 ****
* Return remainder after dividing two signed quads.
*
! * XXX
! * If -1/2 should produce -1 on this machine, this code is wrong.
*/
quad_t
--- 45,49 ----
* Return remainder after dividing two signed quads.
*
! * XXX we assume a % b < 0 iff a < 0, but this is actually machine-dependent.
*/
quad_t
***************
*** 60,64 ****
ua = a, neg = 0;
if (b < 0)
! ub = -(u_quad_t)b, neg ^= 1;
else
ub = b;
--- 59,63 ----
ua = a, neg = 0;
if (b < 0)
! ub = -(u_quad_t)b;
else
ub = b;