MODULE testdiv ; (*!m2pim *) FROM libc IMPORT printf, exit ; CONST min = -40 ; max = 100 ; (* assert - *) PROCEDURE assert (b: BOOLEAN) ; BEGIN IF NOT b THEN printf ("logic failed\n"); exit (1) END END assert ; (* divtest - *) PROCEDURE divtest (a, b: INTEGER) : BOOLEAN ; BEGIN (* firstly catch division by 0. *) IF b = 0 THEN RETURN FALSE END ; IF max < 0 THEN (* case 2 range is always negative. *) (* in which case a division will be illegal as result will be positive. *) RETURN FALSE ELSIF min >= 0 THEN (* case 1 both min / max are positive. *) IF a < b * min THEN (* underflow. *) RETURN FALSE END ; IF b > a DIV min THEN (* underflow. *) RETURN FALSE END ELSE (* case 3 mixed range. *) IF (a >= 0) AND (b > 0) THEN (* both operands positive therefore cannot overflow. *) RETURN TRUE ELSIF (a < 0) AND (b < 0) THEN (* both operands negative, check for overflow. *) RETURN b < a DIV min ELSE (* mixed range of operands - only need to test underflow. *) IF a < 0 THEN assert (b >= 0) ; (* can underflow if. *) RETURN b > a DIV max ELSE assert (a >= 0) ; assert (b < 0) ; (* b is < 0 and the result can underflow if. *) (* printf ("a = %d, b = %d, b * min = %d\n", a, b, b * min); *) RETURN a DIV b >= min END END END ; HALT END divtest ; (* assertFailed - *) PROCEDURE assertFailed (a, b: INTEGER; message: ARRAY OF CHAR) ; BEGIN printf ("assert failed ") ; printf (message) ; printf (" %d DIV %d = %d\n", a, b, a DIV b) END assertFailed ; (* inRange - *) PROCEDURE inRange (v: INTEGER) : BOOLEAN ; BEGIN RETURN (v >= min) AND (v <= max) END inRange ; PROCEDURE runTest ; VAR a, b: INTEGER ; BEGIN FOR a := min TO max DO FOR b := min TO max DO IF b # 0 THEN IF divtest (a, b) THEN (* printf ("a = %d, b = %d, a DIV b = %d\n", a, b, a DIV b); *) printf ("a = %d, b = %d\n", a, b); IF NOT inRange (a DIV b) THEN assertFailed (a, b, "divtest marked this as good") ; END ELSE IF inRange (a DIV b) THEN assertFailed (a, b, "divtest marked this as bad") END END END END END END runTest ; BEGIN runTest END testdiv.