1 /** @file exam_numeric.cpp
3 * These exams creates some numbers and check the result of several boolean
4 * tests on these numbers like is_integer() etc... */
7 * GiNaC Copyright (C) 1999-2000 Johannes Gutenberg University Mainz, Germany
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 /* Simple and maybe somewhat pointless consistency tests of assorted tests and
28 static unsigned exam_numeric1(void)
31 numeric test_int1(42);
33 numeric test_rat1 = test_int1; test_rat1 /= test_int2;
34 test_rat1 = -test_rat1; // -42/5
35 numeric test_crat = test_rat1+I*test_int2; // 5*I-42/5
39 if (!test_int1.is_integer()) {
41 << " erroneously not recognized as integer" << endl;
44 if (!test_int1.is_rational()) {
46 << " erroneously not recognized as rational" << endl;
50 if (!test_rat1.is_rational()) {
52 << " erroneously not recognized as rational" << endl;
55 if (test_rat1.is_integer()) {
57 << " erroneously recognized as integer" << endl;
61 if (!test_crat.is_crational()) {
63 << " erroneously not recognized as complex rational" << endl;
67 int i = numeric(1984).to_int();
69 clog << "conversion of " << i
70 << " from numeric to int failed" << endl;
75 if (!e1.info(info_flags::posint)) {
76 clog << "expression " << e1
77 << " erroneously not recognized as positive integer" << endl;
82 if (ex_to_numeric(e2).is_integer()) {
83 clog << "expression " << e2
84 << " erroneously recognized as integer" << endl;
88 // The next two were two actual bugs in CLN till June, 12, 1999:
89 test_rat1 = numeric(3)/numeric(2);
90 test_rat1 += test_rat1;
91 if (!test_rat1.is_integer()) {
92 clog << "3/2 + 3/2 erroneously not integer 3 but instead "
96 test_rat1 = numeric(3)/numeric(2);
97 numeric test_rat2 = test_rat1 + numeric(1); // 5/2
98 test_rat2 -= test_rat1; // 1
99 if (!test_rat2.is_integer()) {
100 clog << "5/2 - 3/2 erroneously not integer 1 but instead "
101 << test_rat2 << endl;
108 /* We had some fun with a bug in CLN that caused it to loop forever when
109 * calculating expt(a,b) if b is a rational and a a nonnegative integer.
110 * Implementing a workaround sadly introduced another bug on May 28th 1999
111 * that was fixed on May 31st. The workaround turned out to be stupid and
112 * the original bug in CLN was finally killed on September 2nd. */
113 static unsigned exam_numeric2(void)
117 ex zero = numeric(0);
119 ex three = numeric(3);
121 // The hang in this code was the reason for the original workaround
122 if (pow(two,two/three)==42) {
123 clog << "pow(2,2/3) erroneously returned 42" << endl;
124 ++result; // cannot happen
127 // Actually, this used to raise a FPE after introducing the workaround
128 if (two*zero!=zero) {
129 clog << "2*0 erroneously returned " << two*zero << endl;
133 // And this returned a cl_F due to the implicit call of numeric::power()
135 if (!six.info(info_flags::integer)) {
136 clog << "2*3 erroneously returned the non-integer " << six << endl;
140 // The fix in the workaround left a whole which was fixed hours later...
141 ex another_zero = pow(zero,numeric(1)/numeric(2));
142 if (!another_zero.is_zero()) {
143 clog << "pow(0,1/2) erroneously returned" << another_zero << endl;
150 /* Assorted tests to ensure some crucial functions behave exactly as specified
151 * in the documentation. */
152 static unsigned exam_numeric3(void)
155 numeric calc_rem, calc_quo;
158 // check if irem(a, b) and irem(a, b, q) really behave like Maple's
159 // irem(a, b) and irem(a, b, 'q') as advertised in our documentation.
160 // These overloaded routines indeed need to be checked separately since
161 // internally they might be doing something completely different:
162 a = 23; b = 4; calc_rem = irem(a, b);
164 clog << "irem(" << a << "," << b << ") erroneously returned "
168 a = 23; b = -4; calc_rem = irem(a, b);
170 clog << "irem(" << a << "," << b << ") erroneously returned "
174 a = -23; b = 4; calc_rem = irem(a, b);
175 if (calc_rem != -3) {
176 clog << "irem(" << a << "," << b << ") erroneously returned "
180 a = -23; b = -4; calc_rem = irem(a, b);
181 if (calc_rem != -3) {
182 clog << "irem(" << a << "," << b << ") erroneously returned "
186 // and now the overloaded irem(a,b,q):
187 a = 23; b = 4; calc_rem = irem(a, b, calc_quo);
188 if (calc_rem != 3 || calc_quo != 5) {
189 clog << "irem(" << a << "," << b << ",q) erroneously returned "
190 << calc_rem << " with q=" << calc_quo << endl;
193 a = 23; b = -4; calc_rem = irem(a, b, calc_quo);
194 if (calc_rem != 3 || calc_quo != -5) {
195 clog << "irem(" << a << "," << b << ",q) erroneously returned "
196 << calc_rem << " with q=" << calc_quo << endl;
199 a = -23; b = 4; calc_rem = irem(a, b, calc_quo);
200 if (calc_rem != -3 || calc_quo != -5) {
201 clog << "irem(" << a << "," << b << ",q) erroneously returned "
202 << calc_rem << " with q=" << calc_quo << endl;
205 a = -23; b = -4; calc_rem = irem(a, b, calc_quo);
206 if (calc_rem != -3 || calc_quo != 5) {
207 clog << "irem(" << a << "," << b << ",q) erroneously returned "
208 << calc_rem << " with q=" << calc_quo << endl;
211 // check if iquo(a, b) and iquo(a, b, r) really behave like Maple's
212 // iquo(a, b) and iquo(a, b, 'r') as advertised in our documentation.
213 // These overloaded routines indeed need to be checked separately since
214 // internally they might be doing something completely different:
215 a = 23; b = 4; calc_quo = iquo(a, b);
217 clog << "iquo(" << a << "," << b << ") erroneously returned "
221 a = 23; b = -4; calc_quo = iquo(a, b);
222 if (calc_quo != -5) {
223 clog << "iquo(" << a << "," << b << ") erroneously returned "
227 a = -23; b = 4; calc_quo = iquo(a, b);
228 if (calc_quo != -5) {
229 clog << "iquo(" << a << "," << b << ") erroneously returned "
233 a = -23; b = -4; calc_quo = iquo(a, b);
235 clog << "iquo(" << a << "," << b << ") erroneously returned "
239 // and now the overloaded iquo(a,b,r):
240 a = 23; b = 4; calc_quo = iquo(a, b, calc_rem);
241 if (calc_quo != 5 || calc_rem != 3) {
242 clog << "iquo(" << a << "," << b << ",r) erroneously returned "
243 << calc_quo << " with r=" << calc_rem << endl;
246 a = 23; b = -4; calc_quo = iquo(a, b, calc_rem);
247 if (calc_quo != -5 || calc_rem != 3) {
248 clog << "iquo(" << a << "," << b << ",r) erroneously returned "
249 << calc_quo << " with r=" << calc_rem << endl;
252 a = -23; b = 4; calc_quo = iquo(a, b, calc_rem);
253 if (calc_quo != -5 || calc_rem != -3) {
254 clog << "iquo(" << a << "," << b << ",r) erroneously returned "
255 << calc_quo << " with r=" << calc_rem << endl;
258 a = -23; b = -4; calc_quo = iquo(a, b, calc_rem);
259 if (calc_quo != 5 || calc_rem != -3) {
260 clog << "iquo(" << a << "," << b << ",r) erroneously returned "
261 << calc_quo << " with r=" << calc_rem << endl;
268 /* Now we perform some less trivial checks about several functions which should
269 * return exact numbers if possible. */
270 static unsigned exam_numeric4(void)
275 // square roots of squares of integers:
277 for (int i=0; i<42; ++i) {
278 if (!sqrt(numeric(i*i)).is_integer()) {
283 clog << "One or more square roots of squares of integers did not return exact integers" << endl;
287 // square roots of squares of rationals:
289 for (int num=0; num<41; ++num) {
290 for (int den=1; den<42; ++den) {
291 if (!sqrt(numeric(num*num)/numeric(den*den)).is_rational()) {
297 clog << "One or more square roots of squares of rationals did not return exact integers" << endl;
304 /* This test examines that simplifications of the form 5^(3/2) -> 5*5^(1/2)
305 * are carried out properly. */
306 static unsigned exam_numeric5(void)
310 // A variation of one of Ramanujan's wonderful identities must be
311 // verifiable with very primitive means:
312 ex e1 = pow(1 + pow(3,numeric(1,5)) - pow(3,numeric(2,5)),3);
313 ex e2 = expand(e1 - 10 + 5*pow(3,numeric(3,5)));
315 clog << "expand((1+3^(1/5)-3^(2/5))^3-10+5*3^(3/5)) returned "
316 << e2 << " instead of 0." << endl;
323 unsigned exam_numeric(void)
327 cout << "examining consistency of numeric types" << flush;
328 clog << "----------consistency of numeric types:" << endl;
330 result += exam_numeric1(); cout << '.' << flush;
331 result += exam_numeric2(); cout << '.' << flush;
332 result += exam_numeric3(); cout << '.' << flush;
333 result += exam_numeric4(); cout << '.' << flush;
334 result += exam_numeric5(); cout << '.' << flush;
337 cout << " passed " << endl;
338 clog << "(no output)" << endl;
340 cout << " failed " << endl;