1/*
2 * test3500 - 3500 series of the regress.cal test suite
3 *
4 * Copyright (C) 1999  Ernest Bowen and Landon Curt Noll
5 *
6 * Primary author:  Ernest Bowen
7 *
8 * Calc is open software; you can redistribute it and/or modify it under
9 * the terms of the version 2.1 of the GNU Lesser General Public License
10 * as published by the Free Software Foundation.
11 *
12 * Calc is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 * or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU Lesser General
15 * Public License for more details.
16 *
17 * A copy of version 2.1 of the GNU Lesser General Public License is
18 * distributed with calc under the filename COPYING-LGPL.  You should have
19 * received a copy with calc; if not, write to Free Software Foundation, Inc.
20 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 *
22 * Under source code control:	1995/12/18 22:50:46
23 * File existed as early as:	1995
24 *
25 * Share and enjoy!  :-)	http://www.isthe.com/chongo/tech/comp/calc/
26 */
27
28/*
29 * Stringent tests of the functions frem, fcnt, gcdrem.
30 *
31 * testf(n) gives n tests of frem(x,y) and fcnt(x,y) with randomly
32 *	integers x and y generated so that x = f * y^k where f, y and
33 *	k are randomly generated.
34 *
35 * testg(n) gives n tests of gcdrem(x,y) with x and y generated as for
36 *	testf(n).
37 *
38 * testh(n,N) gives n tests of g = gcdrem(x,y) where x and y are products of
39 *	powers of small primes some of which are common to both x and y.
40 *	This test uses f = abs(x) and iteratively f = frem(f,p) where
41 *	p varies over the prime divisors of y; the final value for f
42 *	should equal g.	 For both x and y the primes are raised to the
43 *	power rand(N); N defaults to 10.
44 *
45 * If verbose is > 1, the numbers x, y and values for some of the
46 *	functions will be displayed.  Numbers used in testf()
47 *	and testg() occasionally have thousands of digits.
48 *
49 */
50
51
52defaultverbose = 1;	/* default verbose value */
53
54define testfrem(x,y,verbose)
55{
56	local f, n;
57
58	if (isnull(verbose)) verbose = defaultverbose;
59
60	f = frem(x,y);
61	n = fcnt(x,y);
62	if (verbose > 1)
63		printf("frem = %d, fcnt = %d\n\n", f, n);
64	if (abs(x) != f * abs(y)^n)
65		return 1;
66	if (!ismult(x,y) || abs(y) <= 1) {
67		if (f != abs(x))
68			return 2;
69		if (n != 0)
70			return 3;
71		return 0;
72	}
73	if (x == 0) {
74		if (f != 0 || n != 0)
75			return 4;
76		return 0;
77	}
78	if (f < 0 || !isint(f) || n <= 0)
79		return 5;
80	if (ismult(f, y))
81		return 6;
82	if (!ismult(x, y^n))
83		return 7;
84	if (ismult(x, y^(n+1)))
85		return 8;
86	return 0;
87}
88
89define testgcdrem(x,y,verbose)
90{
91	local d, q;
92
93	if (isnull(verbose)) verbose = defaultverbose;
94
95	d = gcdrem(x,y);
96	if (verbose > 1)
97		printf("gcdrem = %d\n\n", d);
98	if (y == 0) {
99		if (d != 1)
100			return 1;
101		return 0;
102	}
103	if (x == 0) {
104		if (d != 0)
105			return 2;
106		return 0;
107	}
108	if (d <= 0)
109		return 3;
110	q = x/d;
111	if (!isint(q))
112		return 4;
113	if (!isrel(d, y))
114		return 5;
115	if (!isrel(d, q))
116		return 6;
117	return 0;
118}
119
120define testf(str,n,verbose)
121{
122	local m, x, y, i, k, y1, f1, f, fail;
123
124	if (isnull(verbose))
125		verbose = defaultverbose;
126	if (verbose > 0) {
127		print str:":",:;
128	}
129	m = 0;
130	for (i = 0; i < n; i++) {
131		y1 = rand(2^rand(1,6));
132		y = rand(-(2^y1), 1 + 2^y1);
133		f1 = rand(2^rand(1,11));
134		f = rand(-(2^f1), 1+2^f1);
135		k = rand(1,1+2^10);
136		x = f * y^k;
137		if (verbose > 1) {
138			printf("x = %d\n", x);
139			printf("y = %d\n", y);
140		}
141		fail = testfrem(x,y,verbose);
142		if (fail != 0) {
143			printf("*** Failure %d on loop %d\n", fail, i);
144			if (verbose > 1) {
145				printf("    x = %d\n", x);
146				printf("    y = %d\n", y);
147			}
148			m++;
149		}
150	}
151
152	if (verbose > 0) {
153		if (m) {
154			printf("*** %d error(s)\n", m);
155		} else {
156			printf("no errors\n");
157		}
158	}
159	return m;
160}
161
162
163define testg(str,n,verbose)
164{
165	local m, x, y, i, k, y1, f1, f, fail;
166
167	if (isnull(verbose))
168		verbose = defaultverbose;
169	if (verbose > 0) {
170		print str:":",:;
171	}
172	m = 0;
173	for (i = 0; i < n; i++) {
174		y1 = rand(2^rand(1,6));
175		y = rand(-(2^y1), 1 + 2^y1);
176		f1 = rand(2^rand(1,11));
177		f = rand(-(2^f1), 1+2^f1);
178		k = rand(1,1+2^10);
179		x = f * y^k;
180		if (verbose > 1) {
181			printf("x = %d\n", x);
182			printf("y = %d\n", y);
183		}
184		fail = testgcdrem(x,y,verbose);
185		if (fail != 0) {
186			printf("*** Failure %d on loop %d\n", fail, i);
187			if (verbose > 1) {
188				printf("    x = %d\n", x);
189				printf("    y = %d\n", y);
190			}
191			m++;
192		}
193	}
194
195	if (verbose > 0) {
196		if (m) {
197			printf("*** %d error(s)\n", m);
198		} else {
199			printf("no errors\n");
200		}
201	}
202	return m;
203}
204
205define testh(str,n,N,verbose)
206{
207	local m, i, x, y, f, g;
208
209	if (isnull(verbose))
210		verbose = defaultverbose;
211	if (verbose > 0) {
212		print str:":",:;
213	}
214	m = 0;
215	if (isnull(N))
216		N = 61;
217	for (i = 0; i < n; i ++) {
218		x = 2^rand(N)*3^rand(N) * 7^rand(N) * 11^rand(N) * 101^rand(N);
219		y = 2^rand(N) * 3^rand(N) * 5^rand(N) * 11^rand(N) * 53^rand(N);
220		if (rand(2)) x = -x;
221		if (rand(2)) y = -y;
222
223		if (verbose > 1) {
224			printf("x = %d\n", x);
225			printf("y = %d\n", y);
226		}
227		f = abs(x);
228		g = gcdrem(x,y);
229		if (ismult(y,2)) f = frem(f,2);
230		if (ismult(y,3)) f = frem(f,3);
231		if (ismult(y,5)) f = frem(f,5);
232		if (ismult(y,11)) f = frem(f,11);
233		if (ismult(y,53)) f = frem(f,53);
234
235		if (f != g) {
236			printf("*** Failure on loop %d\n", i);
237			if (verbose > 1) {
238				printf("    x = %d\n", x);
239				printf("    y = %d\n", y);
240				printf("    f = %d\n", f);
241				printf("    g = %d\n", g);
242			}
243			m++;
244		}
245	}
246
247	if (verbose > 0) {
248		if (m) {
249			printf("*** %d error(s)\n", m);
250		} else {
251			printf("no errors\n");
252		}
253	}
254	return m;
255}
256
257/*
258 * test3500 - perform all of the above tests a bunch of times
259 */
260define test3500(verbose, tnum, n, N)
261{
262	/* set test parameters */
263	if (isnull(verbose)) {
264		verbose = defaultverbose;
265	}
266	if (isnull(tnum)) {
267		tnum = 3501;	/* default test number */
268	}
269	if (isnull(n)) {
270		n = 200;
271	}
272	if (isnull(N)) {
273		N = 61;
274	}
275
276	/*
277	 * test a lot of stuff
278	 */
279	srand(3500e3500);
280	err += testf(strcat(str(tnum++), ": frem/fcnt"), n, verbose);
281	err += testg(strcat(str(tnum++), ": gcdrem"), n, verbose);
282	err += testh(strcat(str(tnum++),": gcdrem #2"), n, N, verbose);
283	if (verbose > 1) {
284		if (err) {
285			print "***", err, "error(s) found in testall";
286		} else {
287			print "no errors in testall";
288		}
289	}
290	return tnum;
291}
292