98dc90faa9800a50f9271c296cd79ec69312afed
[ginac.git] / check / exam_factor.cpp
1 /** @file exam_factor.cpp
2  *
3  *  Factorization test suite. */
4
5 /*
6  *  GiNaC Copyright (C) 1999-2015 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 symbol w("w"), x("x"), y("y"), z("z");
30
31 static unsigned check_factor(const ex& e)
32 {
33         ex ee = e.expand();
34         ex answer = factor(ee);
35         if ( answer.expand() != ee || answer != e ) {
36                 clog << "factorization of " << e << " == " << ee << " gave wrong result: " << answer << endl;
37                 return 1;
38         }
39         return 0;
40 }
41
42 static unsigned exam_factor1()
43 {
44         unsigned result = 0;
45         ex e;
46         symbol x("x");
47         lst syms;
48         syms.append(x);
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;
117         syms = x, y, z;
118         
119         e = ex("x+y", syms);
120         result += check_factor(e);
121
122         e = ex("(x^2-y+1)*(x+y)", syms);
123         result += check_factor(e);
124
125         e = ex("-2*(x+y)*(x-y)", syms);
126         result += check_factor(e);
127
128         e = ex("(16+x^2*z^3)*(-17+3*x-5*z)*(2*x+3*z)*(x-y^2-z^3)", syms);
129         result += check_factor(e);
130
131         e = ex("(x-y*z)*(x-y^2-z^3)*(x+y+z)", syms);
132         result += check_factor(e);
133         
134         e = ex("-(y^2-x+z^3)*x*(x+y+z)", syms);
135         result += check_factor(e);
136         
137         e = ex("-316*(3*x-4*z)*(2*x+3*z)*(x+y)*(-1+x)", syms);
138         result += check_factor(e);
139         
140         e = ex("(x+x^3+z^2)*(3*x-4*z)", syms);
141         result += check_factor(e);
142         
143         e = ex("250*(-3+x)*(4*z-3*x)*(x^3+z^2+x)*x", syms);
144         result += check_factor(e);
145         
146         e = ex("327*(x+z^2+x^3)*(3*x-4*z)*(-7+5*x-x^3)*(1+x+x^2)", syms);
147         result += check_factor(e);
148         
149         e = ex("x-y^2-z^3", syms);
150         result += check_factor(e);
151         
152         e = ex("-390*(7+3*x^4)*(2+x^2)*(x-z^3-y^2)", syms);
153         result += check_factor(e);
154         
155         e = ex("55*(1+x)^2*(3*x-4*z)*(1+x+x^2)*(x+x^3+z^2)", syms);
156         result += check_factor(e);
157         
158         e = ex("x+y*x-1", syms);
159         result += check_factor(e);
160         
161         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);
162         result += check_factor(e);
163         
164         e = ex("310*(y+x)*(-1+y-x^2)", syms);
165         result += check_factor(e);
166
167         return result;
168 }
169
170 static unsigned exam_factor3()
171 {
172         unsigned result = 0;
173         ex e;
174         symbol k("k"), n("n");
175         lst syms;
176         syms = k, n;
177         
178         e = ex("1/2*(-3+3*k-n)*(-2+3*k-n)*(-1+3*k-n)", syms);
179         result += check_factor(e);
180
181         e = ex("1/4*(2*k-n)*(-1+2*k-n)", syms);
182         result += check_factor(e);
183
184         return result;
185 }
186
187 static unsigned check_factorization(const exvector& factors)
188 {
189         ex e = (new mul(factors))->setflag(status_flags::dynallocated);
190         ex ef = factor(e.expand());
191         if (ef.nops() != factors.size()) {
192                 clog << "wrong number of factors, expected " << factors.size() <<
193                         ", got " << ef.nops();
194                 return 1;
195         }
196         for (size_t i = 0; i < ef.nops(); ++i) {
197                 if (find(factors.begin(), factors.end(), ef.op(i)) == factors.end()) {
198                         clog << "wrong factorization: term not found: " << ef.op(i);
199                         return 1;
200                 }
201         }
202         return 0;
203 }
204
205 static unsigned factor_integer_content_bug()
206 {
207         parser reader;
208         exvector factors;
209         factors.push_back(reader("x+y+x*y"));
210         factors.push_back(reader("3*x+2*y"));
211         return check_factorization(factors);
212 }
213
214 unsigned exam_factor()
215 {
216         unsigned result = 0;
217
218         cout << "examining polynomial factorization" << flush;
219
220         result += exam_factor1(); cout << '.' << flush;
221         result += exam_factor2(); cout << '.' << flush;
222         result += exam_factor3(); cout << '.' << flush;
223         result += factor_integer_content_bug();
224         cout << '.' << flush;
225
226         return result;
227 }
228
229 int main(int argc, char** argv)
230 {
231         return exam_factor();
232 }