mirror of
https://github.com/lcn2/calc.git
synced 2025-08-16 01:03:29 +03:00
To make the meaning a bit more clear in cal/regress.cal, we have renamed the following test calc resource files that are related to the calc regression test suite: cal/test1700.cal -> cal/test8000.read.cal cal/test2300.cal -> cal/test2300.obj_incdec.cal cal/test2600.cal -> cal/test2600.numfunc.cal cal/test2700.cal -> cal/test2700.isqrt.cal cal/test3100.cal -> cal/test3100.matobj.cal cal/test3400.cal -> cal/test3400.trig.cal cal/test4000.cal -> cal/test4000.ptest.cal cal/test4100.cal -> cal/test4100.redc.cal cal/test4600.cal -> cal/test4600.fileop.cal cal/test5100.cal -> cal/test5100.newdecl.cal cal/test5200.cal -> cal/test5200.globstat.cal cal/test8400.cal -> cal/test8400.quit.cal cal/test8500.cal -> cal/test8500.divmod.cal cal/test8600.cal -> cal/test8600.maxargs.cal cal/set8700.cal -> cal/test8700.dotest.cal cal/test8900.cal -> cal/test8900.special.cal cal/test9300.cal -> cal/test9300.frem.cal Added to test 94dd, read of a number of new calc resource files that are not already read as a result of the calc regression test suite.
261 lines
5.9 KiB
Plaintext
261 lines
5.9 KiB
Plaintext
/*
|
|
* test8500.divmod - test // and % with various rounding mode for test 85dd
|
|
*
|
|
* Copyright (C) 1999,2021,2023 Ernest Bowen and Landon Curt Noll
|
|
*
|
|
* Primary author: Ernest Bowen
|
|
*
|
|
* Calc is open software; you can redistribute it and/or modify it under
|
|
* the terms of the version 2.1 of the GNU Lesser General Public License
|
|
* as published by the Free Software Foundation.
|
|
*
|
|
* Calc is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
|
|
* Public License for more details.
|
|
*
|
|
* A copy of version 2.1 of the GNU Lesser General Public License is
|
|
* distributed with calc under the filename COPYING-LGPL. You should have
|
|
* received a copy with calc; if not, write to Free Software Foundation, Inc.
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* Under source code control: 1999/11/12 20:59:59
|
|
* File existed as early as: 1999
|
|
*
|
|
* Share and enjoy! :-) http://www.isthe.com/chongo/tech/comp/calc/
|
|
*/
|
|
|
|
/*
|
|
* Tests of // and % operators
|
|
*/
|
|
|
|
|
|
global err_8500; /* divmod_8500 error count */
|
|
global L_8500; /* list of problem values */
|
|
global ver_8500; /* test verbosity - see setting comment near bottom */
|
|
global old_seed_8500; /* old srand() seed */
|
|
|
|
/*
|
|
* save the config state so that we can change it and restore later
|
|
*/
|
|
global cfg_8500 = config("all");
|
|
|
|
|
|
/*
|
|
* onetest_8500 - perform one division / remainder test
|
|
*
|
|
* Returns:
|
|
* 0 = test was successful
|
|
* >0 = test error indicator
|
|
*/
|
|
define onetest_8500(a,b,rnd) {
|
|
local q, r, s, S;
|
|
|
|
/*
|
|
* set a random rounding mode
|
|
*/
|
|
config("quo", rnd), config("mod", rnd);
|
|
|
|
/*
|
|
* perform the division and mod
|
|
*/
|
|
q = a // b;
|
|
r = a % b;
|
|
|
|
/*
|
|
* verify the fundamental math
|
|
*/
|
|
if (a != q * b + r)
|
|
return 1;
|
|
|
|
/*
|
|
* determine if the rounding worked
|
|
*/
|
|
if (b) {
|
|
if (rnd & 16)
|
|
s = sgn(abs(r) - abs(b)/2);
|
|
else
|
|
s = sgn(abs(r) - abs(b));
|
|
|
|
if (s < 0 || r == 0)
|
|
return 0;
|
|
|
|
if (s > 0)
|
|
return 2;
|
|
|
|
if (((rnd & 16) && s == 0) || !(rnd & 16)) {
|
|
|
|
S = sgn(r) * sgn(b); /* This is sgn(a/b) - a//b */
|
|
switch (rnd & 15) {
|
|
case 0: return (S < 0) ? 3 : 0;
|
|
case 1: return (S > 0) ? 4 : 0;
|
|
case 2: return (S != sgn(a)*sgn(b)) ? 5 : 0;
|
|
case 3: return (S != -sgn(a)*sgn(b)) ? 6 : 0;
|
|
break;
|
|
case 4: return (S != sgn(b)) ? 7 : 0;
|
|
case 5: return (S != -sgn(b)) ? 8 : 0;
|
|
case 6: return (S != sgn(a)) ? 9 : 0;
|
|
case 7: return (S != -sgn(a)) ? 10 : 0;
|
|
case 8: return (isodd(q)) ? 11 : 0;
|
|
case 9: return (iseven(q)) ? 12 : 0;
|
|
case 10: return (iseven(q) != (a/b > 0)) ? 13:0;
|
|
case 11: return (isodd(q) != (a/b > 0)) ? 14:0;
|
|
case 12: return (iseven(q) != (b > 0)) ? 15 : 0;
|
|
case 13: return (isodd(q) != (b > 0)) ? 16 : 0;
|
|
case 14: return (iseven(q) != (a > 0)) ? 17 : 0;
|
|
case 15: return (isodd(q) != (a > 0)) ? 18 : 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* all is well
|
|
*/
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*
|
|
* divmod_8500 - perform a bunch of pseudo-random // and % test
|
|
*
|
|
* divmod_8500(N, M1, M2) will perform N tests with randomly chosen integers
|
|
* a, b with abs(a) < M1, abs(b) < M2, which with 50% probability are
|
|
* converted to a = (2 * a + 1) * b, b = 2 * b (to give case where
|
|
* a / b is an integer + 1/2).
|
|
*
|
|
* N defaults to 10, M1 to 2^128, M2 to 2^64
|
|
*
|
|
* The testnum, if > 0, is used while printing a failure or success.
|
|
*
|
|
* The rounding parameter is randomly chosen.
|
|
*
|
|
* After a run of divmod_8500 the a, b, rnd values which gave failure are
|
|
* stored in the list L_8500. L_8500[0], L_8500[1], L_8500[2] are a, b,
|
|
* rnd for the first* test, etc.
|
|
*/
|
|
define divmod_8500(N = 10, M1 = 2^128, M2 = 2^64, testnum = 0)
|
|
{
|
|
local a, b, i, v, rnd;
|
|
local errmsg; /* error message to display */
|
|
|
|
/*
|
|
* firewall
|
|
*/
|
|
if (!isint(M1) || M1 < 2)
|
|
quit "Bad second arg for dtest";
|
|
|
|
if (!isint(M2) || M2 < 2)
|
|
quit "Bad third arg for dtest";
|
|
|
|
/*
|
|
* test setup
|
|
*/
|
|
err_8500 = 0;
|
|
L_8500 = list();
|
|
|
|
/*
|
|
* perform the random results
|
|
*/
|
|
for (i = 0; i < N; i++) {
|
|
|
|
/*
|
|
* randomly select two values in the range controlled by M1,M2
|
|
*/
|
|
a = rand(-M1+1, M1);
|
|
b = rand(-M2+1, M2);
|
|
if (rand(2)) {
|
|
a = (2 * a + 1) * b;
|
|
b *= 2;
|
|
}
|
|
|
|
/*
|
|
* select one of the 32 rounding modes at random
|
|
*/
|
|
rnd = rand(32);
|
|
|
|
/*
|
|
* ver_8500 pre-test reporting
|
|
*/
|
|
if (ver_8500 > 1)
|
|
printf("Test %d: a = %d, b = %d, rnd = %d\n",
|
|
i, a, b, rnd);
|
|
|
|
/*
|
|
* perform the actual test
|
|
*/
|
|
v = onetest_8500(a, b, rnd);
|
|
|
|
/*
|
|
* individual test analysis
|
|
*/
|
|
if (v != 0) {
|
|
err_8500++;
|
|
if (ver_8500 != 0) {
|
|
if (testnum > 0) {
|
|
errmsg = strprintf(
|
|
"Failure %d on test %d", v, i);
|
|
prob(errmsg);
|
|
} else {
|
|
printf("Failure %d on test %d", v, i);
|
|
}
|
|
}
|
|
append(L_8500, a, b, rnd);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* report in the results
|
|
*/
|
|
if (err_8500) {
|
|
if (testnum > 0) {
|
|
errmsg = strprintf(
|
|
"%d: divmod_8500(%d,,,%d): %d failures",
|
|
testnum, N, testnum, err_8500);
|
|
prob(errmsg);
|
|
} else {
|
|
printf("%s failure%s", err_8500,
|
|
(err_8500 > 1) ? "s" : "");
|
|
}
|
|
} else {
|
|
if (testnum > 0) {
|
|
errmsg = strprintf("%d: divmod_8500(%d,,,%d)",
|
|
testnum, N, testnum);
|
|
vrfy(err_8500 == 0, errmsg);
|
|
} else {
|
|
print "No failure";
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
* ver_8500 != 0 displays failures; ver_8500 > 1 displays all numbers tested
|
|
*/
|
|
ver_8500 = 0;
|
|
print '8501: ver_8500 = 0';
|
|
old_seed_8500 = srand(31^61);
|
|
print '8502: old_seed_8500 = srand(31^61)';
|
|
|
|
/*
|
|
* do the tests
|
|
*/
|
|
divmod_8500(250, 2^128, 2^1, 8503);
|
|
divmod_8500(250, 2^128, 2^64, 8504);
|
|
divmod_8500(250, 2^256, 2^64, 8505);
|
|
divmod_8500(250, 2^1024, 2^64, 8506);
|
|
divmod_8500(250, 2^1024, 2^128, 8507);
|
|
divmod_8500(250, 2^16384, 2^1024, 8508);
|
|
divmod_8500(1000, 2^128, 2^64, 8509);
|
|
|
|
/*
|
|
* restore state
|
|
*/
|
|
config("all", cfg_8500),;
|
|
print '8510: config("all", cfg_8500),';
|
|
srand(old_seed_8500),;
|
|
print '8511: srand(old_seed_8500),';
|
|
|
|
/*
|
|
* finished with 8500 tests
|
|
*/
|
|
print '8512: Ending test_divmod';
|