Clean up check suite a little bit.
[ginac.git] / check / exam_factor.cpp
1 /** @file exam_factor.cpp
2  *
3  *  Factorization test suite. */
4
5 /*
6  *  GiNaC Copyright (C) 1999-2020 Johannes Gutenberg University Mainz, Germany
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  */
22
23 #include "ginac.h"
24 using namespace GiNaC;
25
26 #include <iostream>
27 using namespace std;
28
29 static unsigned check_factor(const ex& e)
30 {
31         ex ee = e.expand();
32         ex answer = factor(ee);
33         if ( answer.expand() != ee || answer != e ) {
34                 clog << "factorization of " << e << " == " << ee << " gave wrong result: " << answer << endl;
35                 return 1;
36         }
37         return 0;
38 }
39
40 static unsigned exam_factor1()
41 {
42         unsigned result = 0;
43         ex e;
44         symbol x("x");
45         lst syms = {x};
46
47         e = 1;
48         result += check_factor(e);
49
50         e = ex("1+x-x^3", syms);
51         result += check_factor(e);
52
53         e = ex("1+x^6+x", syms);
54         result += check_factor(e);
55
56         e = ex("1-x^6+x", syms);
57         result += check_factor(e);
58
59         e = ex("(1+x)^3", syms);
60         result += check_factor(e);
61
62         e = ex("(x+1)*(x+4)", syms);
63         result += check_factor(e);
64
65         e = ex("x^6-3*x^5+x^4-3*x^3-x^2-3*x+1", syms);
66         result += check_factor(e);
67
68         e = ex("(-1+x)^3*(1+x)^3*(1+x^2)", syms);
69         result += check_factor(e);
70
71         e = ex("-(-168+20*x-x^2)*(30+x)", syms);
72         result += check_factor(e);
73
74         e = ex("x^2*(x-3)^2*(x^3-5*x+7)", syms);
75         result += check_factor(e);
76
77         e = ex("-6*x^2*(x-3)", syms);
78         result += check_factor(e);
79
80         e = ex("x^16+11*x^4+121", syms);
81         result += check_factor(e);
82
83         e = ex("x^8-40*x^6+352*x^4-960*x^2+576", syms);
84         result += check_factor(e);
85
86         e = ex("x*(2+x^2)*(1+x+x^3+x^2+x^6+x^5+x^4)*(1+x)^2*(1-x+x^2)^2*(-1+x)", syms);
87         result += check_factor(e);
88
89         e = ex("(x+4+x^2-x^3+43*x^4)*(x+1-x^2-3*x^3+4*x^4)", syms);
90         result += check_factor(e);
91
92         e = ex("-x^2*(x-1)*(1+x^2)", syms);
93         result += check_factor(e);
94
95         e = x;
96         result += check_factor(e);
97
98         // x^37 + 1
99         e = ex("(1+x)*(1+x^2-x^29-x^11-x^25-x^9-x^35+x^20-x^3+x^16-x^15-x-x^13+x^28+x^24-x^33+x^8-x^19+x^36+x^12-x^27+x^10-x^23+x^18+x^14+x^34-x^31+x^32+x^30-x^5+x^26+x^4+x^22-x^21-x^7-x^17+x^6)", syms);
100         result += check_factor(e);
101
102         e = ex("(1+4*x)*x^2*(1-4*x+16*x^2)*(3+5*x+92*x^3)", syms);
103         result += check_factor(e);
104
105         e = ex("(77+11*x^3+25*x^2+27*x+102*x^4)*(85+57*x^3+92*x^2+29*x+66*x^4)", syms);
106         result += check_factor(e);
107
108         return result;
109 }
110
111 static unsigned exam_factor2()
112 {
113         unsigned result = 0;
114         ex e;
115         symbol x("x"), y("y"), z("z");
116         lst syms = {x, y, z};
117         
118         e = ex("x+y", syms);
119         result += check_factor(e);
120
121         e = ex("(x^2-y+1)*(x+y)", syms);
122         result += check_factor(e);
123
124         e = ex("-2*(x+y)*(x-y)", syms);
125         result += check_factor(e);
126
127         e = ex("(16+x^2*z^3)*(-17+3*x-5*z)*(2*x+3*z)*(x-y^2-z^3)", syms);
128         result += check_factor(e);
129
130         e = ex("(x-y*z)*(x-y^2-z^3)*(x+y+z)", syms);
131         result += check_factor(e);
132         
133         e = ex("-(y^2-x+z^3)*x*(x+y+z)", syms);
134         result += check_factor(e);
135         
136         e = ex("-316*(3*x-4*z)*(2*x+3*z)*(x+y)*(-1+x)", syms);
137         result += check_factor(e);
138         
139         e = ex("(x+x^3+z^2)*(3*x-4*z)", syms);
140         result += check_factor(e);
141         
142         e = ex("250*(-3+x)*(4*z-3*x)*(x^3+z^2+x)*x", syms);
143         result += check_factor(e);
144         
145         e = ex("327*(x+z^2+x^3)*(3*x-4*z)*(-7+5*x-x^3)*(1+x+x^2)", syms);
146         result += check_factor(e);
147         
148         e = ex("x-y^2-z^3", syms);
149         result += check_factor(e);
150         
151         e = ex("-390*(7+3*x^4)*(2+x^2)*(x-z^3-y^2)", syms);
152         result += check_factor(e);
153         
154         e = ex("55*(1+x)^2*(3*x-4*z)*(1+x+x^2)*(x+x^3+z^2)", syms);
155         result += check_factor(e);
156         
157         e = ex("x+y*x-1", syms);
158         result += check_factor(e);
159         
160         e = ex("390*(-1+x^6-x)*(7+3*x^4)*(2+x^2)*(y+x)*(-1+y-x^2)*(1+x^2+x)^2", syms);
161         result += check_factor(e);
162         
163         e = ex("310*(y+x)*(-1+y-x^2)", syms);
164         result += check_factor(e);
165
166         return result;
167 }
168
169 static unsigned exam_factor3()
170 {
171         unsigned result = 0;
172         ex e;
173         symbol k("k"), n("n");
174         lst syms = {k, n};
175         
176         e = ex("1/2*(-3+3*k-n)*(-2+3*k-n)*(-1+3*k-n)", syms);
177         result += check_factor(e);
178
179         e = ex("1/4*(2*k-n)*(-1+2*k-n)", syms);
180         result += check_factor(e);
181
182         return result;
183 }
184
185 static unsigned check_factor_expanded(const ex& e)
186 {
187         ex ee = e.expand();
188         ex answer = factor(ee);
189         if ( answer.expand() != ee || (!is_a<mul>(answer) && !is_a<power>(answer)) ) {
190                 clog << "factorization of " << e << " == " << ee << " gave wrong result: " << answer << endl;
191                 return 1;
192         }
193         return 0;
194 }
195
196 static unsigned exam_factor_content()
197 {
198         unsigned result = 0;
199         ex e;
200         symbol x("x"), y("y");
201
202         // Fixed 2013-07-28 by Alexei Sheplyakov in factor_univariate().
203         e = ex("174247781*x^2-1989199947807987/200000000000000", lst{x});
204         result += check_factor(e);
205
206         // Fixed 2014-05-18 by Alexei Sheplyakov in factor_multivariate().
207         e = ex("(x+y+x*y)*(3*x+2*y)", lst{x, y});
208         result += check_factor(e);
209
210         return result;
211 }
212
213 static unsigned exam_factor_wang()
214 {
215         // these 15 polynomials are from the appendix of P.S.Wang,
216         // "An Improved Multivariate Polynomial Factoring Algorithm"
217         unsigned result = 0;
218         ex e;
219         symbol u("u"), w("w"), x("x"), y("y"), z("z");
220
221         e = ex("(z+x*y+10)*(x*z+y+30)*(y*z+x+20)", lst{x, y, z});
222         result += check_factor_expanded(e);
223
224         e = ex("(x^3*(z+y)+y-11)*(x^2*(z^2+y^2)+y+90)", lst{x, y, z});
225         result += check_factor_expanded(e);
226
227         e = ex("(y*z^3+x*y*z+y^2+x^3)*(x*(z^4+1)+z+x^3*y^2)", lst{x, y, z});
228         result += check_factor_expanded(e);
229
230         e = ex("(z^2-x^3*y+3)*(z^2+x*y^3)*(z^2+x^3*y^4)*(y^4*z^2+x^2*z+5)", lst{x, y, z});
231         result += check_factor_expanded(e);
232
233         e = ex("(z^2+x^3*y^4+u^2)*((y^2+x)*z^2+3*u^2*x^3*y^4*z+19*y^2)*(u^2*y^4*z^2+x^2*z+5)", lst{u, x, y, z});
234         result += check_factor_expanded(e);
235
236         e = ex("(w^4*z^3-x*y^2*z^2-w^4*x^5*y^6-w^2*x^3*y)*(-x^5*z^3+y*z+x^2*y^3)"
237                "*(w^4*z^6+y^2*z^3-w^2*x^2*y^2*z^2+x^5*z-x^4*y^2-w^3*x^3*y)", lst{w, x, y, z});
238         result += check_factor_expanded(e);
239
240         e = ex("(z+y+x-3)^3*(z+y+x-2)^2", lst{x, y, z});
241         result += check_factor_expanded(e);
242
243         e = ex("(-15*y^2*z^16+29*w^4*x^12*y^12*z^3+21*x^3*z^2+3*w^15*y^20)"
244                "*(-z^31-w^12*z^20+y^18-y^14+x^2*y^2+x^21+w^2)", lst{w, x, y, z});
245         result += check_factor_expanded(e);
246
247         e = ex("u^4*x*z^2*(6*w^2*y^3*z^2+18*u^2*w^3*x*z^2+15*u*z^2+10*u^2*w*x*y^3)"
248                "*(-44*u*w*x*y^4*z^4-25*u^2*w^3*y*z^4+8*u*w*x^3*z^4-32*u^2*w^4*y^4*z^3"
249                "+48*u^2*x^2*y^3*z^3-12*y^3*z^2+2*u^2*w*x^2*y^2-11*u*w^2*x^3*y-4*w^2*x)", lst{u, w, x, y, z});
250         result += check_factor_expanded(e);
251
252         e = ex("(31*u^2*x*z+35*w^2*y^2+6*x*y+40*w*x^2)*(u^2*w^2*x*y^2*z^2+24*u^2*w*x*y^2*z^2"
253                "+12*u^2*x*y^2*z^2+24*u^2*x^2*y*z^2+43*w*x*y*z^2+31*w^2*y*z^2+8*u^2*w^2*z^2"
254                "+44*u*w^2*z^2+37*u^2*y^2*z+41*y^2*z+12*w*x^2*y*z+21*u^2*w*x*y*z+23*x*y*z"
255                "+47*u^2*w^2*z+13*u*w^2*x^2*y^2+22*x*y^2+42*u^2*w^2*y^2+29*w^2*y^2+27*u*w^2*x^2*y"
256                "+37*w^2*x*z+39*u*w*x*z+43*u*x^2*y+24*x*y+9*u^2*w*x^2+22*u^2*w^2)", lst{u, w, x, y, z});
257         result += check_factor_expanded(e);
258
259         e = ex("x*y*(-13*u^3*w^2*x*y*z^3+w^3*z^3+4*u*x*y^2+47*x*y)"
260                "*(43*u*x^3*y^3*z^3+36*u^2*w^3*x*y*z^3+14*w^3*x^3*y^3*z^2-29*w^3*x*y^3*z^2"
261                "-20*u^2*w^2*x^2*y^2*z^2+36*u^2*w*x*y^3*z-48*u*x^3*y^2*z+5*u*w*x^2*y^3"
262                "+36*u*w^2*y^3-9*u*w*y^3-23*u*w*x^3*y^2+46*u*x^3*y^2+8*x*y^2+31*u^2*w^3*y^2"
263                "-9*u^2*y^2+45*x^3-46*u^2*w*x)", lst{u, w, x, y, z});
264         result += check_factor_expanded(e);
265
266         e = ex("(z+y+x-3)^3", lst{x, y, z});
267         result += check_factor_expanded(e);
268
269         e = ex("(3*z^3+2*w*z-9*y^3-y^2+45*x^3)*(w^2*z^3+47*x*y-w^2)", lst{w, x, y, z});
270         result += check_factor_expanded(e);
271
272         e = ex("(-18*x^4*y^5+22*y^5-26*x^3*y^4-38*x^2*y^4+29*x^2*y^3-41*x^4*y^2+37*x^4)"
273                "*(33*x^5*y^6+11*y^2+35*x^3*y-22*x^4)", lst{x, y, z});
274         result += check_factor_expanded(e);
275
276         e = ex("x^6*y^3*z^2*(3*z^3+2*w*z-8*x*y^2+14*w^2*y^2-y^2+18*x^3*y)"
277                "*(-12*w^2*x*y*z^3+w^2*z^3+3*x*y^2+29*x-w^2)", lst{w, x, y, z});
278         result += check_factor_expanded(e);
279
280         return result;
281 }
282
283 unsigned exam_factor()
284 {
285         unsigned result = 0;
286
287         cout << "examining polynomial factorization" << flush;
288
289         result += exam_factor1(); cout << '.' << flush;
290         result += exam_factor2(); cout << '.' << flush;
291         result += exam_factor3(); cout << '.' << flush;
292         result += exam_factor_content(); cout << '.' << flush;
293         result += exam_factor_wang(); cout << '.' << flush;
294
295         return result;
296 }
297
298 int main(int argc, char** argv)
299 {
300         return exam_factor();
301 }