1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
|
(* Tests for overflow in div and mod. *)
fun dv (i, j) = LargeInt.toInt(LargeInt.div(LargeInt.fromInt i, LargeInt.fromInt j));
fun md (i, j) = LargeInt.toInt(LargeInt.mod(LargeInt.fromInt i, LargeInt.fromInt j));
fun check(i, j) = if i = j then () else raise Fail "wrong";
case Int.maxInt of SOME m => check(m div 2, dv(m, 2)) | NONE => ();
case Int.maxInt of SOME m => check(m div ~2, dv(m, ~2)) | NONE => (); (* Should not overflow. *)
case Int.minInt of SOME m => check(m mod ~1, 0) | NONE => (); (* Should not overflow. *)
(* Dividing the minimum int by ~1 should raise overflow. *)
case Int.minInt of SOME m => ((dv(m, ~1); raise Fail "wrong") handle Overflow => ()) | NONE => ();
(* Random number generator. *)
local
fun rmod x y = x - y * Real.realFloor (x / y);
val a = 16807.0;
val m = 2147483647.0;
val random_seed = ref 1.0;
in
fun random () =
let
val r = rmod (a * ! random_seed) m
in
(* This can overflow 31-bit fixed precision.
TODO: Find a random number generator that doesn't *)
random_seed := r;
Real.toInt IEEEReal.TO_NEGINF r
handle Overflow => random()
end
end;
fun doFor f 0 = () | doFor f n = (f(); doFor f (n-1));
fun doit () =
let
val a = random() and b = random()
fun checkDiv(i, j) =
if i div j = dv(i, j)
then ()
else raise Fail (concat["Error - ", Int.toString i, " div ", Int.toString j])
and checkMod(i, j) =
if i mod j = md(i, j)
then ()
else raise Fail (concat["Error - ", Int.toString i, " mod ", Int.toString j])
in
checkDiv(a, b); checkMod(a, b);
checkDiv(~a, b); checkMod(~a, b);
checkDiv(a, ~b); checkMod(a, ~b);
checkDiv(~a, ~b); checkMod(~a, ~b)
end;
doFor doit 100;
|