1 /*************************************************************************************
2  *  Copyright (C) 2014 by Percy Camilo T. Aucahuasi <percy.camilo.ta@gmail.com>      *
3  *                                                                                   *
4  *  This program is free software; you can redistribute it and/or                    *
5  *  modify it under the terms of the GNU General Public License                      *
6  *  as published by the Free Software Foundation; either version 2                   *
7  *  of the License, or (at your option) any later version.                           *
8  *                                                                                   *
9  *  This program is distributed in the hope that it will be useful,                  *
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of                   *
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                    *
12  *  GNU General Public License for more details.                                     *
13  *                                                                                   *
14  *  You should have received a copy of the GNU General Public License                *
15  *  along with this program; if not, write to the Free Software                      *
16  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA   *
17  *************************************************************************************/
18 
19 #include "commandstest.h"
20 
21 #include <QTest>
22 
23 #include "analyzer.h"
24 #include <config-analitza.h>
25 
26 using Analitza::Expression;
27 
QTEST_MAIN(CommandsTest)28 QTEST_MAIN( CommandsTest )
29 
30 CommandsTest::CommandsTest(QObject *parent)
31  : QObject(parent)
32 {}
33 
~CommandsTest()34 CommandsTest::~CommandsTest()
35 {}
36 
initTestCase()37 void CommandsTest::initTestCase()
38 {
39     a=new Analitza::Analyzer;
40 }
41 
cleanupTestCase()42 void CommandsTest::cleanupTestCase()
43 {
44     delete a;
45 }
46 
testCorrect_data()47 void CommandsTest::testCorrect_data()
48 {
49     QTest::addColumn<QStringList>("expression");
50     QTest::addColumn<QString>("result");
51 
52     QStringList script;
53 
54     script.clear();
55     script << QStringLiteral("range(10)");
56     QTest::newRow("simple range") << script << "list { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }";
57 
58     script.clear();
59     script << QStringLiteral("range(-1.5, 2)");
60     QTest::newRow("range(-1.5, 2)") << script << "list { -1.5, -0.5, 0.5, 1.5 }";
61 
62     script.clear();
63     script << QStringLiteral("range(0, 1, 0.2)");
64     QTest::newRow("range(0, 1, 0.2)") << script << "list { 0, 0.2, 0.4, 0.6, 0.8, 1 }";
65 
66     script.clear();
67     script << QStringLiteral("vector(3, -2.3)");
68     QTest::newRow("simple fill vector") << script << "vector { -2.3, -2.3, -2.3 }";
69 
70     script.clear();
71     script << QStringLiteral("7*vector(34, 14.2)[23]");
72     QTest::newRow("select fill vector") << script << "99.4";
73 
74     script.clear();
75     script << QStringLiteral("seq := range(14, 20, 2)");
76     script << QStringLiteral("vector(seq)");
77     QTest::newRow("vector by range/seq") << script << "vector { 14, 16, 18, 20 }";
78 
79     script.clear();
80     script << QStringLiteral("matrix(3, 2, -15.7)");
81     QTest::newRow("simple fill matrix") << script << "matrix { matrixrow { -15.7, -15.7 }, matrixrow { -15.7, -15.7 }, matrixrow { -15.7, -15.7 } }";
82 
83     script.clear();
84     script << QStringLiteral("matrix(2)");
85     QTest::newRow("simple fill square matrix") << script << "matrix { matrixrow { 0, 0 }, matrixrow { 0, 0 } }";
86 
87     script.clear();
88     script << QStringLiteral("matrix(3, 2)");
89     QTest::newRow("simple matrix") << script << "matrix { matrixrow { 0, 0 }, matrixrow { 0, 0 }, matrixrow { 0, 0 } }";
90 
91     script.clear();
92     script << QStringLiteral("matrix(3, 2, -9.8)[2][1]");
93     QTest::newRow("select simple matrix") << script << "-9.8";
94 
95     script.clear();
96     script << QStringLiteral("matrix(vector{2,3}, vector{7, 4})");
97     QTest::newRow("matrix by vectors/columns") << script << "matrix { matrixrow { 2, 7 }, matrixrow { 3, 4 } }";
98 
99     script.clear();
100     script << QStringLiteral("matrix(matrixrow{2,3}, matrixrow{7, 4})");
101     QTest::newRow("matrix by rows") << script << "matrix { matrixrow { 2, 3 }, matrixrow { 7, 4 } }";
102 
103     script.clear();
104     script << QStringLiteral("A := matrix{matrixrow{13,6}, matrixrow{-2,5}}");
105     script << QStringLiteral("matrix(vector{2,3}, vector{7, 4}) + A");
106     QTest::newRow("matrix by vectors/columns + A") << script << "matrix { matrixrow { 15, 13 }, matrixrow { 1, 9 } }";
107 
108     script.clear();
109     script << QStringLiteral("A := matrix{matrixrow{2, 3, 6}, matrixrow{-5, 0, 2.3}}");
110     script << QStringLiteral("matrix(2, 3, -9) + A");
111     QTest::newRow("fill + A") << script << "matrix { matrixrow { -7, -6, -3 }, matrixrow { -14, -9, -6.7 } }";
112 
113     script.clear();
114     script << QStringLiteral("A := matrix{matrixrow{2, 3}, matrixrow{-5, 1}}");
115     script << QStringLiteral("B := matrix{matrixrow{12, 13}, matrixrow{-15, 11}}");
116     script << QStringLiteral("blockmatrix(matrixrow{A, B})");
117     QTest::newRow("simple block matrix") << script << "matrix { matrixrow { 2, 3, 12, 13 }, matrixrow { -5, 1, -15, 11 } }";
118 
119     const QString resultblockmatrix = QStringLiteral("matrix { matrixrow { 1, 8, 7, 6 }, matrixrow { 3, 5, 0, 2 }, matrixrow { 1, 4, 9, 3 } }");
120 
121     script.clear();
122     script << QStringLiteral("A := matrix(vector{1,3}, vector{8,5})");
123     script << QStringLiteral("B := matrix{matrixrow{7,6}, matrixrow{0,2}}");
124     script << QStringLiteral("C := matrix(matrixrow{1,4})");
125     script << QStringLiteral("D := matrix(vector{9}, vector{3})");
126     script << QStringLiteral("blockmatrix(matrixrow{A, B}, matrixrow{C, D})");
127     QTest::newRow("block matrix 4 blocks conf 1") << script << resultblockmatrix;
128 
129     script.clear();
130     script << QStringLiteral("A := matrix{matrixrow{1,8,7}, matrixrow{3,5,0}}");
131     script << QStringLiteral("B := matrix(vector{6,2})");
132     script << QStringLiteral("C := matrix(matrixrow{1,4,9})");
133     script << QStringLiteral("D := matrix(1,1,3)");
134     script << QStringLiteral("blockmatrix(matrixrow{A, B}, matrixrow{C, D})");
135     QTest::newRow("block matrix by rows, conf 2") << script << resultblockmatrix;
136 
137     script.clear();
138     script << QStringLiteral("A := matrix(matrixrow{1,8})");
139     script << QStringLiteral("B := transpose(matrix(diag(diag(7,6))))");
140     script << QStringLiteral("C := matrix{matrixrow{3,5}}");
141     script << QStringLiteral("D := matrix(matrixrow{0,2})");
142     script << QStringLiteral("E := matrix(vector{1},vector{4})");
143     script << QStringLiteral("F := matrix{matrixrow{9,3}}");
144     script << QStringLiteral("blockmatrix(matrixrow{A, B}, matrixrow{C, D}, matrixrow{E, F})");
145     QTest::newRow("block matrix by rows, conf 3") << script << resultblockmatrix;
146 
147     script.clear();
148     script << QStringLiteral("A := matrix(vector{1,3}, vector{8,5})");
149     script << QStringLiteral("B := matrix(matrixrow{1,4})");
150     script << QStringLiteral("C := matrix{matrixrow{7,6}, matrixrow{0,2}}");
151     script << QStringLiteral("D := matrix(vector{9}, vector{3})");
152     script << QStringLiteral("blockmatrix(vector{A, B}, vector{C, D})");
153     QTest::newRow("block matrix by cols, conf 1") << script << resultblockmatrix;
154 
155     script.clear();
156     script << QStringLiteral("A := matrix{matrixrow{1,8}}");
157     script << QStringLiteral("B := matrix(matrixrow{3,5})");
158     script << QStringLiteral("C := matrix(matrixrow{1,4})");
159     script << QStringLiteral("D := matrix{matrixrow{7,6}}");
160     script << QStringLiteral("E := matrix(matrixrow{0,2})");
161     script << QStringLiteral("F := matrix(matrixrow{9,3})");
162     script << QStringLiteral("blockmatrix(vector{A, B, C}, vector{D, E, F})");
163     QTest::newRow("block matrix by cols, conf 2") << script << resultblockmatrix;
164 
165     script.clear();
166     script << QStringLiteral("matrix(2,5)");
167     QTest::newRow("simple 0") << script << "matrix { matrixrow { 0, 0, 0, 0, 0 }, matrixrow { 0, 0, 0, 0, 0 } }";
168 
169     script.clear();
170     script << QStringLiteral("identitymatrix(3)");
171     QTest::newRow("simple I") << script << "matrix { matrixrow { 1, 0, 0 }, matrixrow { 0, 1, 0 }, matrixrow { 0, 0, 1 } }";
172 
173     script.clear();
174     script << QStringLiteral("identitymatrix(3)-identitymatrix(3)");
175     QTest::newRow("I - I") << script << "matrix { matrixrow { 0, 0, 0 }, matrixrow { 0, 0, 0 }, matrixrow { 0, 0, 0 } }";
176 
177     script.clear();
178     script << QStringLiteral("0*identitymatrix(3)");
179     QTest::newRow("0*I") << script << "matrix { matrixrow { 0, 0, 0 }, matrixrow { 0, 0, 0 }, matrixrow { 0, 0, 0 } }";
180 
181     script.clear();
182     script << QStringLiteral("matrix(3,3) + identitymatrix(3)");
183     QTest::newRow("0 + I") << script << "matrix { matrixrow { 1, 0, 0 }, matrixrow { 0, 1, 0 }, matrixrow { 0, 0, 1 } }";
184 
185     script.clear();
186     script << QStringLiteral("diag(5, 3.2, 6, -9)");
187     QTest::newRow("simple diag") << script << "matrix { matrixrow { 5, 0, 0, 0 }, matrixrow { 0, 3.2, 0, 0 }, matrixrow { 0, 0, 6, 0 }, matrixrow { 0, 0, 0, -9 } }";
188 
189     script.clear();
190     script << QStringLiteral("diag(vector{5, 3.2, 6, -9})");
191     QTest::newRow("simple diag by vector") << script << "matrix { matrixrow { 5, 0, 0, 0 }, matrixrow { 0, 3.2, 0, 0 }, matrixrow { 0, 0, 6, 0 }, matrixrow { 0, 0, 0, -9 } }";
192 
193     script.clear();
194     script << QStringLiteral("diag(1, 1, 1) - identitymatrix(3)");
195     QTest::newRow("zeromatrix: diag - I") << script << "matrix { matrixrow { 0, 0, 0 }, matrixrow { 0, 0, 0 }, matrixrow { 0, 0, 0 } }";
196 
197     script.clear();
198     script << QStringLiteral("diag(vector{1, 1, 1}) - identitymatrix(3)");
199     QTest::newRow("zeromatrix: diag by vector - I") << script << "matrix { matrixrow { 0, 0, 0 }, matrixrow { 0, 0, 0 }, matrixrow { 0, 0, 0 } }";
200 
201     script.clear();
202     script << QStringLiteral("diag(5, 7.8, -0.6, 3.5)[3][3] + diag(5, 7.8, -0.6, 3.5)[2][3]");
203     QTest::newRow("selector diag") << script << "-0.6";
204 
205     script.clear();
206     script << QStringLiteral("v := vector{5, 7.8, -0.6, 3.5}");
207     script << QStringLiteral("diag(v)[3][3] + diag(v)[2][3]");
208     QTest::newRow("selector diag by vector") << script << "-0.6";
209 
210     script.clear();
211     script << QStringLiteral("blockdiag(matrix{matrixrow{1, 3}, matrixrow{-6, 8}}, matrix{matrixrow{5, 6}, matrixrow{14, -1.2}})");
212     QTest::newRow("simple block diagonal") << script << "matrix { matrixrow { 1, 3, 0, 0 }, matrixrow { -6, 8, 0, 0 }, matrixrow { 0, 0, 5, 6 }, matrixrow { 0, 0, 14, -1.2 } }";
213 
214     script.clear();
215     script << QStringLiteral("I := identitymatrix(3)");
216     script << QStringLiteral("A := matrix(2,3, -6)");
217     script << QStringLiteral("B := 3*I");
218     script << QStringLiteral("blockdiag(I, A, B)");
219     QTest::newRow("block diagonal") << script << "matrix { matrixrow { 1, 0, 0, 0, 0, 0, 0, 0, 0 }, matrixrow { 0, 1, 0, 0, 0, 0, 0, 0, 0 }, matrixrow { 0, 0, 1, 0, 0, 0, 0, 0, 0 }, matrixrow { 0, 0, 0, -6, -6, -6, 0, 0, 0 }, matrixrow { 0, 0, 0, -6, -6, -6, 0, 0, 0 }, matrixrow { 0, 0, 0, 0, 0, 0, 3, 0, 0 }, matrixrow { 0, 0, 0, 0, 0, 0, 0, 3, 0 }, matrixrow { 0, 0, 0, 0, 0, 0, 0, 0, 3 } }";
220 
221     script.clear();
222     script << QStringLiteral("tridiag(-2.1, 3.6, 48, 5)");
223     QTest::newRow("simple tridiag") << script << "matrix { matrixrow { 3.6, 48, 0, 0, 0 }, matrixrow { -2.1, 3.6, 48, 0, 0 }, matrixrow { 0, -2.1, 3.6, 48, 0 }, matrixrow { 0, 0, -2.1, 3.6, 48 }, matrixrow { 0, 0, 0, -2.1, 3.6 } }";
224 
225     script.clear();
226     script << QStringLiteral("A := matrix{matrixrow{-7.8, 2.3, 5}, matrixrow{0, -1.2, cos(pi)}, matrixrow{-45, 9.6, -2.3}}");
227     script << QStringLiteral("tridiag(-8, 10, 7.2, 3) - identitymatrix(3) + A");
228     QTest::newRow("tridiag - I + A") << script << "matrix { matrixrow { 1.2, 9.5, 5 }, matrixrow { -8, 7.8, 6.2 }, matrixrow { -45, 1.6, 6.7 } }";
229 
230     script.clear();
231     script << QStringLiteral("A := matrix{matrixrow{-7.8, 2.3, 5}, matrixrow{0, -12, 1}, matrixrow{-45, 9.6, cos(pi)}}");
232     script << QStringLiteral("diag(A)");
233     QTest::newRow("simple diag(A)") << script << "vector { -7.8, -12, -1 }";
234 
235     script.clear();
236     script << QStringLiteral("A := matrix{matrixrow{8, 2.3, 5}, matrixrow{-45, -cos(pi), 12}}");
237     script << QStringLiteral("diag(A)");
238     QTest::newRow("getdiag fat") << script << "vector { 8, 1 }";
239 
240     script.clear();
241     script << QStringLiteral("A := matrix{matrixrow{8, 2.3, 1}, matrixrow{3, 32, 2}, matrixrow{-45, 12, 3}, matrixrow{1, 0, 3}, matrixrow{-5, 1, 0}}");
242     script << QStringLiteral("diag(A)");
243     QTest::newRow("getdiag skinny") << script << "vector { 8, 32, 3 }";
244 
245     script.clear();
246     script << QStringLiteral("A := matrix{matrixrow{-7.8, 2.3, 5}, matrixrow{0, -12, 1}, matrixrow{-45, 9.6, cos(pi)}}");
247     script << QStringLiteral("diag(A)[2]");
248     QTest::newRow("selector getdiag") << script << "-12";
249 
250     script.clear();
251     script << QStringLiteral("v := vector{5,5,0}");
252     script << QStringLiteral("A := matrix{matrixrow{0, -1, 2}, matrixrow{4, 0, -3.2}, matrixrow{5.8, -15, 0}}");
253     script << QStringLiteral("B := matrix(3,3, 4.5)");
254     script << QStringLiteral("D := diag(v)");
255     script << QStringLiteral("I := identitymatrix(3)");
256     script << QStringLiteral("O := matrix(3,3)");
257     script << QStringLiteral("T := tridiag(2,1,8,3)");
258     script << QStringLiteral("A + B + D - cos(pi)*I + O + T");
259     QTest::newRow("complex exp") << script << "matrix { matrixrow { 11.5, 11.5, 6.5 }, matrixrow { 10.5, 11.5, 9.3 }, matrixrow { 10.3, -8.5, 6.5 } }";
260 
261 // 3.6     48      0     9    80
262 // 2.1    3.2     49    20   100
263 //   1   -2.1    3.6    47    90
264 //   0     -7   -2.1   3.3    42
265 //   5      4      3  -2.1   3.5
266     const QString square = QStringLiteral("A := matrix{matrixrow{3.6, 48, 0, 9, 80}, matrixrow {2.1, 3.2, 49, 20, 100}, matrixrow{1, -2.1, 3.6, 47, 90}, matrixrow{0, -7, -2.1, 3.3, 42}, matrixrow{5, 4,  3, -2.1, 3.5}}");
267 
268     script.clear();
269     script << square;
270     script << QStringLiteral("diag(A,2)");
271     QTest::newRow("getndiag square +2") << script << "vector { 0, 20, 90 }";
272 
273     script.clear();
274     script << square;
275     script << QStringLiteral("diag(A,-2)");
276     QTest::newRow("getndiag square -2") << script << "vector { 1, -7, 3 }";
277 
278     script.clear();
279     script << square;
280     script << QStringLiteral("diag(A,-3)");
281     QTest::newRow("getndiag square -3") << script << "vector { 0, 4 }";
282 
283     script.clear();
284     script << square;
285     script << QStringLiteral("diag(A,3)");
286     QTest::newRow("getndiag square +3") << script << "vector { 9, 100 }";
287 
288     script.clear();
289     script << square;
290     script << QStringLiteral("diag(A,-3)");
291     QTest::newRow("getndiag square -3") << script << "vector { 0, 4 }";
292 
293     script.clear();
294     script << square;
295     script << QStringLiteral("diag(A,4)[1]");
296     QTest::newRow("selector getndiag square corner +") << script << "80";
297 
298     script.clear();
299     script << square;
300     script << QStringLiteral("diag(A,-4)[1]");
301     QTest::newRow("selector getndiag square corner -") << script << "5";
302 
303 //  3.6    42     0      9     80   4   15
304 // -4.1   7.8    45      0    100   6    7
305 //    1   2.2   3.6     47      0   8    9
306 //    0     0  -2.3    5.6     48   2    1
307 //    2     4     3   -2.1    3.6   3    5
308     const QString fat = QStringLiteral("A := matrix{matrixrow{3.6, 42, 0, 9, 80, 4, 15}, matrixrow{-4.1, 7.8, 45, 0, 100, 6,7}, matrixrow{1, 2.2, 5.6, 47, 0 , 8, 9}, matrixrow{0, 0, -2.3, 3.6, 48, 2,1}, matrixrow{2, 4, 3, -2.1, 3.6, 3,5}}");
309 
310     script.clear();
311     script << fat;
312     script << QStringLiteral("diag(A,5)");
313     QTest::newRow("getndiag fat +5") << script << "vector { 4, 7 }";
314 
315     script.clear();
316     script << fat;
317     script << QStringLiteral("diag(A,1)");
318     QTest::newRow("getndiag fat +1") << script << "vector { 42, 45, 47, 48, 3 }";
319 
320     script.clear();
321     script << fat;
322     script << QStringLiteral("diag(A,-1)");
323     QTest::newRow("getndiag fat -1") << script << "vector { -4.1, 2.2, -2.3, -2.1 }";
324 
325     script.clear();
326     script << fat;
327     script << QStringLiteral("diag(A,6)[1]");
328     QTest::newRow("selector getndiag fat corner +") << script << "15";
329 
330     script.clear();
331     script << fat;
332     script << QStringLiteral("diag(A,-4)[1]");
333     QTest::newRow("selector getndiag fat corner -") << script << "2";
334 
335 //  3.6    42
336 // -4.1   7.8
337 //    1   2.2
338 //    0     1
339 //    2     4
340     const QString skinny = QStringLiteral("A := matrix{matrixrow{3.6, 42}, matrixrow{-4.1, 7.8}, matrixrow{1, 2.2}, matrixrow{0, 1}, matrixrow{2, 4}}");
341 
342     script.clear();
343     script << fat;
344     script << QStringLiteral("diag(A,1)[1]");
345     QTest::newRow("selector getndiag skinny corner +") << script << "42";
346 
347     script.clear();
348     script << skinny;
349     script << QStringLiteral("diag(A,-1)");
350     QTest::newRow("getndiag skinny -1") << script << "vector { -4.1, 2.2 }";
351 
352     script.clear();
353     script << skinny;
354     script << QStringLiteral("diag(A,-3)");
355     QTest::newRow("getndiag skinny -3") << script << "vector { 0, 4 }";
356 
357     script.clear();
358     script << skinny;
359     script << QStringLiteral("diag(A,-4)");
360     QTest::newRow("getndiag skinny -4") << script << "vector { 2 }";
361 
362     script.clear();
363     script << skinny;
364     script << QStringLiteral("isdiag(A)");
365     QTest::newRow("is not diag") << script << "false";
366 
367     script.clear();
368     script << QStringLiteral("iszeromatrix(matrix(8,5))");
369     QTest::newRow("is zero matrix") << script << "true";
370 
371     script.clear();
372     script << QStringLiteral("isidentitymatrix(identitymatrix(5))");
373     QTest::newRow("Id is identity matrix") << script << "true";
374 
375     script.clear();
376     script << QStringLiteral("isidentitymatrix(blockdiag(identitymatrix(3), matrix{matrixrow{1}}, identitymatrix(2)))");
377     QTest::newRow("block of Id is Id matrix") << script << "true";
378 
379     script.clear();
380     script << QStringLiteral("isdiag(identitymatrix(4))");
381     QTest::newRow("Id is diag matrix") << script << "true";
382 
383 #ifdef HAVE_EIGEN3
384     script.clear();
385     script << QStringLiteral("eigenvalues(identitymatrix(4))");
386     QTest::newRow("eigenvalues: from Id") << script << "list { 1, 1, 1, 1 }";
387 
388     script.clear();
389     script << QStringLiteral("eigenvalues(matrix(vector{3,4}, vector{-2, -1}))");
390     QTest::newRow("eigenvalues: full complex") << script << "list { 1+2*i, 1-2*i }";
391 
392     script.clear();
393     script << QStringLiteral("eigenvectors(identitymatrix(4))");
394     QTest::newRow("eigenvectors: from Id") << script << "list { vector { 1, 0, 0, 0 }, vector { 0, 1, 0, 0 }, vector { 0, 0, 1, 0 }, vector { 0, 0, 0, 1 } }";
395 
396     script.clear();
397     script << QStringLiteral("eigenvectors(matrix(vector{3,4}, vector{-2, -1}))");
398     QTest::newRow("complex eigenvectors") << script << "list { vector { -0.408248290464+0.408248290464*i, 0.816496580928*i }, vector { -0.408248290464-0.408248290464*i, -0.816496580928*i } }";
399 #endif
400 }
401 
testCorrect()402 void CommandsTest::testCorrect()
403 {
404     QFETCH(QStringList, expression);
405     QFETCH(QString, result);
406 
407     Expression last;
408     Analitza::Analyzer b1;
409     foreach(const QString &exp, expression) {
410         Expression e(exp, false);
411         if(!e.isCorrect()) qDebug() << "error:" << e.error();
412         QVERIFY(e.isCorrect());
413 
414         b1.setExpression(e);
415 
416         if(!b1.isCorrect()) qDebug() << "errors: " << b1.errors();
417         QVERIFY(b1.isCorrect());
418         last = b1.calculate();
419         if(!b1.isCorrect()) qDebug() << "errors:" << e.toString() << b1.errors();
420         QVERIFY(b1.isCorrect());
421     }
422     QCOMPARE(last.toString(), result);
423 
424     QString script = expression.join(QStringLiteral("\n"));
425     script+=QLatin1String("\n\n\n");
426     QTextStream stream(&script);
427     a->importScript(&stream);
428     QVERIFY(a->isCorrect());
429 }
430 
testIncorrect_data()431 void CommandsTest::testIncorrect_data()
432 {
433     QTest::addColumn<QString>("expression");
434 
435     QTest::newRow("range: bad input") << "range(list{3,4}-9)";
436     QTest::newRow("range: bad arg type") << "range(list{3}, 31, true)";
437     QTest::newRow("range: bad arg type2") << "range(list{3}, 31)";
438     QTest::newRow("range: bad arg count") << "range(2,3,vector{3}, list{2}, 4)";
439     QTest::newRow("range: bad args1") << "range(2,3,9, list{2}, 4)";
440     QTest::newRow("range: bad args2") << "range(2,3,9, 9, vector{4})";
441     QTest::newRow("range: bad args3") << "range(2,3,9, 9, 3,4,5,5)";
442 
443     QTest::newRow("vector: bad arg type") << "vector(list{23},4)";
444     QTest::newRow("vector: bad number of args") << "vector(4, list{23}, 44)";
445 
446     QTest::newRow("matrix: 0 args") << "matrix()";
447     QTest::newRow("matrix: bad args") << "matrix(list{3}, 31)";
448     QTest::newRow("matrix: invalid parameter") << "matrix(range(list{matrix{2}}))";
449     QTest::newRow("matrix: empty matrix result") << "matrix(0, 0)";
450     QTest::newRow("matrix: fill empty matrix result") << "matrix(0, 0, sin(1))";
451     QTest::newRow("matrix: not all vectors") << "matrix(vector{1}, 3)";
452     QTest::newRow("matrix: not all matrixrow elements") << "matrix(matrixrow{1}, list{2})";
453     QTest::newRow("matrix: not all matrixrow elements 2") << "matrix(matrixrow{1}, vector{2})";
454     QTest::newRow("matrix: neg square") << "matrix(-9)";
455 
456     QTest::newRow("zero matrix: empty matrix result") << "matrix(0, 0)";
457     QTest::newRow("zero matrix: bad number of args") << "matrix()";
458     QTest::newRow("zero matrix: bad number of args") << "matrix(3,list{3},4,6)";
459     QTest::newRow("zero matrix: bad dim") << "matrix(23, -3.5)";
460     QTest::newRow("zero matrix: bad dim2") << "matrix(-23, 5)";
461 
462     QTest::newRow("identity matrix: bad arg") << "identitymatrix(-98)";
463     QTest::newRow("identity matrix: empty matrix result") << "identitymatrix(0)";
464 
465     QTest::newRow("diag: 0 args") << "diag()";
466     QTest::newRow("diag: bad arg, one empty matrix") << "diag(identitymatrix(0))";
467     QTest::newRow("diag: bad arg, one empty matrix2") << "diag(matrix{matrixrow{}})";
468     QTest::newRow("diag: bad diag index") << "diag(matrix(4,6,3.2), -98)";
469     QTest::newRow("diag: bad diag index type") << "diag(matrix(4,6,3.2), list{-98})";
470     QTest::newRow("diag: invalid parameter") << "diag(matrix(-8,5))";
471 
472     QTest::newRow("tridiag: empty matrix result") << "tridiag(1,2,3,0)";
473     QTest::newRow("tridiag: bad number of args") << "tridiag(1,2,2)";
474     QTest::newRow("tridiag: bad number of args2") << "tridiag(1,2,2, 4, list{2})";
475 
476     QTest::newRow("iszeromatrix: bad number of args") << "iszeromatrix()";
477     QTest::newRow("iszeromatrix: empty matrix") << "iszeromatrix(matrix{})";
478     QTest::newRow("iszeromatrix: invalid parameter") << "iszeromatrix(matrix(-8,5))";
479 
480     QTest::newRow("isidentitymatrix: bad number of args") << "isidentitymatrix(matrix{matrixrow{1}}, 2)";
481     QTest::newRow("isidentitymatrix: bad number of args2") << "isidentitymatrix()";
482     QTest::newRow("isidentitymatrix: empty matrix") << "isidentitymatrix(matrix{})";
483     QTest::newRow("isidentitymatrix: empty matrix2") << "isidentitymatrix(matrix{matrixrow{}})";
484     QTest::newRow("isidentitymatrix: invalid parameter") << "isidentitymatrix(matrix(-8,5))";
485     QTest::newRow("isidentitymatrix: invalid parameter2") << "isidentitymatrix(matrix(list{},5))";
486 
487     QTest::newRow("isdiag: bad number of args") << "isdiag(matrix{matrixrow{1}}, 2)";
488     QTest::newRow("isdiag: bad number of args2") << "isdiag()";
489     QTest::newRow("isdiag: empty matrix") << "isdiag(matrix{})";
490     QTest::newRow("isdiag: empty matrix2") << "isdiag(matrix{matrixrow{}})";
491     QTest::newRow("isdiag: invalid parameter") << "isdiag(matrix(-8,5))";
492 
493     QTest::newRow("blockmatrix: bad block matrix size") << "blockmatrix(vector{matrix(1,2), matrix(32,13)})";
494     QTest::newRow("blockmatrix: empty matrix1") << "blockmatrix(vector{matrix{}}, vector{matrix{matrixrow{}}})";
495     QTest::newRow("blockmatrix: empty matrix2") << "blockmatrix(vector{identitymatrix(0)})";
496     QTest::newRow("blockmatrix: bad arg type") << "blockmatrix(vector{-5})";
497     QTest::newRow("blockmatrix: err arg") << "blockmatrix(vector{matrix{-98}})";
498     QTest::newRow("blockmatrix: bad block matrix args size") << "blockmatrix(vector{matrix(1,2), matrix(32,13)}, vector{matrix(7,13)})";
499     QTest::newRow("blockmatrix: bad block matrix args type 1") << "blockmatrix(vector{matrix(32,13), list{23}}, vector{matrix(7,13), matrix(32,1)})";
500     QTest::newRow("blockmatrix: bad block matrix args type 2") << "matrix(vector{list{23}, zeromatrix(32,13)}, vector{zeromatrix(7,13), zeromatrix(32,1)})";
501 
502     QTest::newRow("blockdiag: bad block diag, empty matrix 1") << "blockdiag(matrix(0,0), matrix(2,2,1))";
503     QTest::newRow("blockdiag: empty matrix1") << "blockdiag(matrix{})";
504     QTest::newRow("blockdiag: empty matrix2") << "blockdiag(identitymatrix(0))";
505     QTest::newRow("blockdiag: bad arg type") << "blockdiag(vector{-5})";
506     QTest::newRow("blockdiag: bad block diag, empty matrix 2") << "blockdiag(matrix{matrixrow{1}}, tridiag(1,2,3,0))";
507     QTest::newRow("blockdiag: invalid parameter") << "blockdiag(matrix(-8,5))";
508 
509     QTest::newRow("bad dimensions:2x2identitymatrix and 2x1zeromatrix") << "2*(identitymatrix(2) + matrix(2,1))";
510     QTest::newRow("bad dimensions:2x2identitymatrix and -2x2matrix") << "2*(identitymatrix(2) + matrix(-2, 2,1))";
511 
512 #ifdef HAVE_EIGEN3
513     QTest::newRow("eigenvalues: bad args type1") << "eigenvalues(list{23},4)";
514     QTest::newRow("eigenvalues: bad args type2") << "eigenvalues(list{23})";
515     QTest::newRow("eigenvalues: empty matrix2") << "eigenvalues(matrix{})";
516     QTest::newRow("eigenvalues: empty invalid matrix2") << "eigenvalues(matrix{1}, matrix{})";
517     QTest::newRow("eigenvalues: bad numbe of args") << "eigenvalues(identitymatrix(3), zeromatrix(4,5))";
518     QTest::newRow("eigenvalues: empty matrix") << "eigenvalues(matrix{matrixrow{1,2}}, matrix{})";
519     QTest::newRow("eigenvalues: invalid arg types1") << "eigenvalues(matrix{matrixrow{1,2}}, matrix{matrixrow{list{5},6}})";
520     QTest::newRow("eigenvalues: invalid arg types2") << "eigenvalues(matrix{matrixrow{1,list{2}}})";
521     QTest::newRow("eigenvalues: non square matrix") << "eigenvalues(matrix{matrixrow{1,2,3}})";
522     //TODO nan and inf cases
523 #endif
524 }
525 
testIncorrect()526 void CommandsTest::testIncorrect()
527 {
528     QFETCH(QString, expression);
529 
530     Expression exp(expression, false);
531 
532     if (exp.isCorrect()) {
533         Analitza::Analyzer a;
534         a.setExpression(exp);
535 
536         if (a.isCorrect()) {
537             Expression calc = a.calculate();
538             QVERIFY(!a.isCorrect());
539             QCOMPARE(calc.toString(), QString());
540             qDebug() << "calc errors:" << a.errors();
541 
542             Expression eval = a.evaluate();
543             QVERIFY(!a.isCorrect());
544             QCOMPARE(eval.toString(), QString());
545             qDebug() << "eval errors:" << a.errors();
546         } else {
547             QVERIFY(!a.isCorrect());
548             qDebug() << "set expression errors:" << a.errors();
549         }
550     } else {
551         qDebug() << "expression errors:" << exp.error();
552     }
553 }
554 
555 
556