Switches xv5;
Release 1;

[ Main;

       print "^Division Tester -- release 1 -- Andrew Plotkin -- this program is public domain^^";
       print "This program tests signed multiplication, division, and modulo operations on the \
               Z-machine. All these operations are supposed to be signed. (The Z-spec 0.2 erroneously \
               says they are unsigned; see the Z-machine newsletter #1 for the correction.)^^";
       print "I am assuming the convention that division always rounds towards zero (not towards \
               negative infinity), and (A % B) always has the same sign as A. These conventions seem \
               to be common among existing C/C++ compilers. (But they are not guaranteed by the C and C++ \
               standards. Those only require that (A/B)*B + (A%B) == A, for all A and all nonzero B.)^^";

       TestDiv();

       print "^Hit any key to exit.^";
       Pause();

       quit;
];

[ Pause dummy;
       @read_char 1 dummy;
       return dummy;
];

[ TestOneLine str answer correct;
       print (string) str, " = ", answer;
       if (answer == correct)
               print " (ok)^";
       else
               print " (should be ", correct, "!)^";
];

[ TestDiv x y z;
       x = 13; y = 5; z = x * y;
       TestOneLine("13 * 5", z, 65);
       x = 13; y = -5; z = x * y;
       TestOneLine("13 * -5", z, -65);
       x = -13; y = 5; z = x * y;
       TestOneLine("-13 * 5", z, -65);
       x = -13; y = -5; z = x * y;
       TestOneLine("-13 * -5", z, 65);

       x = 13; y = 5; z = x / y;
       TestOneLine("13 / 5", z, 2);
       x = 13; y = -5; z = x / y;
       TestOneLine("13 / -5", z, -2);
       x = -13; y = 5; z = x / y;
       TestOneLine("-13 / 5", z, -2);
       x = -13; y = -5; z = x / y;
       TestOneLine("-13 / -5", z, 2);

       x = 13; y = 5; z = x % y;
       TestOneLine("13 % 5", z, 3);
       x = 13; y = -5; z = x % y;
       TestOneLine("13 % -5", z, 3);
       x = -13; y = 5; z = x % y;
       TestOneLine("-13 % 5", z, -3);
       x = -13; y = -5; z = x % y;
       TestOneLine("-13 % -5", z, -3);
];