1 /*
2 Qalculate (library)
3
4 Copyright (C) 2003-2007, 2008, 2016, 2018 Hanna Knutsson (hanna.knutsson@protonmail.com)
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 */
11
12 #include "support.h"
13
14 #include "BuiltinFunctions.h"
15 #include "util.h"
16 #include "MathStructure.h"
17 #include "Number.h"
18 #include "Calculator.h"
19 #include "Variable.h"
20 #include "Unit.h"
21
22 #include <sstream>
23 #include <time.h>
24 #include <limits>
25 #include <algorithm>
26
27 #include "MathStructure-support.h"
28
29 using std::string;
30 using std::cout;
31 using std::vector;
32 using std::endl;
33
VectorFunction()34 VectorFunction::VectorFunction() : MathFunction("vector", -1) {
35 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)36 int VectorFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
37 mstruct = vargs;
38 mstruct.setType(STRUCT_VECTOR);
39 return 1;
40 }
MatrixFunction()41 MatrixFunction::MatrixFunction() : MathFunction("matrix", 3) {
42 Argument *arg = new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE);
43 arg->setHandleVector(false);
44 setArgumentDefinition(1, arg);
45 arg = new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE);
46 arg->setHandleVector(false);
47 setArgumentDefinition(2, arg);
48 setArgumentDefinition(3, new VectorArgument());
49 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)50 int MatrixFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
51 size_t rows = (size_t) vargs[0].number().uintValue();
52 size_t columns = (size_t) vargs[1].number().uintValue();
53 mstruct.clearMatrix(); mstruct.resizeMatrix(rows, columns, m_zero);
54 size_t r = 1, c = 1;
55 for(size_t i = 0; i < vargs[2].size(); i++) {
56 if(r > rows || c > columns) {
57 CALCULATOR->error(false, _("Too many elements (%s) for the dimensions (%sx%s) of the matrix."), i2s(vargs[2].size()).c_str(), i2s(rows).c_str(), i2s(columns).c_str(), NULL);
58 break;
59 }
60 mstruct[r - 1][c - 1] = vargs[2][i];
61 if(c == columns) {
62 c = 1;
63 r++;
64 } else {
65 c++;
66 }
67 }
68 return 1;
69 }
RankFunction()70 RankFunction::RankFunction() : MathFunction("rank", 1, 2) {
71 setArgumentDefinition(1, new VectorArgument(""));
72 setArgumentDefinition(2, new BooleanArgument(""));
73 setDefaultValue(2, "1");
74 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)75 int RankFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
76 if(vargs[0].isMatrix()) {
77 MathStructure mvector;
78 mvector.clearVector();
79 size_t rows = vargs[0].size(), cols = vargs[0][0].size();
80 for(size_t i = 0; i < rows; i++) {
81 for(size_t i2 = 0; i2 < cols; i2++) {
82 mvector.addChild(vargs[0][i][i2]);
83 }
84 }
85 if(!mvector.rankVector(vargs[1].number().getBoolean())) return 0;
86 mstruct.clearMatrix();
87 mstruct.resizeMatrix(rows, cols, m_zero);
88 for(size_t i = 0; i < mvector.size(); i++) {
89 mstruct[i / cols][i % cols] = mvector[i];
90 }
91 return 1;
92 }
93 mstruct = vargs[0];
94 return mstruct.rankVector(vargs[1].number().getBoolean());
95 }
SortFunction()96 SortFunction::SortFunction() : MathFunction("sort", 1, 2) {
97 setArgumentDefinition(1, new VectorArgument(""));
98 setArgumentDefinition(2, new BooleanArgument(""));
99 setDefaultValue(2, "1");
100 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)101 int SortFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
102 mstruct = vargs[0];
103 return mstruct.sortVector(vargs[1].number().getBoolean());
104 }
MergeVectorsFunction()105 MergeVectorsFunction::MergeVectorsFunction() : MathFunction("mergevectors", 1, -1) {
106 setArgumentDefinition(1, new VectorArgument(""));
107 setArgumentDefinition(2, new VectorArgument(""));
108 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)109 int MergeVectorsFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
110 mstruct.clearVector();
111 for(size_t i = 0; i < vargs.size(); i++) {
112 if(CALCULATOR->aborted()) return 0;
113 if(vargs[i].isVector()) {
114 for(size_t i2 = 0; i2 < vargs[i].size(); i2++) {
115 mstruct.addChild(vargs[i][i2]);
116 }
117 } else {
118 mstruct.addChild(vargs[i]);
119 }
120 }
121 return 1;
122 }
MatrixToVectorFunction()123 MatrixToVectorFunction::MatrixToVectorFunction() : MathFunction("matrix2vector", 1) {
124 setArgumentDefinition(1, new MatrixArgument());
125 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)126 int MatrixToVectorFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
127 vargs[0].matrixToVector(mstruct);
128 return 1;
129 }
RowFunction()130 RowFunction::RowFunction() : MathFunction("row", 2) {
131 setArgumentDefinition(1, new MatrixArgument());
132 setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE));
133 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)134 int RowFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
135 size_t row = (size_t) vargs[1].number().uintValue();
136 if(row > vargs[0].rows()) {
137 CALCULATOR->error(true, _("Row %s does not exist in matrix."), format_and_print(vargs[1]).c_str(), NULL);
138 return 0;
139 }
140 vargs[0].rowToVector(row, mstruct);
141 return 1;
142 }
ColumnFunction()143 ColumnFunction::ColumnFunction() : MathFunction("column", 2) {
144 setArgumentDefinition(1, new MatrixArgument());
145 setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE));
146 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)147 int ColumnFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
148 size_t col = (size_t) vargs[1].number().uintValue();
149 if(col > vargs[0].columns()) {
150 CALCULATOR->error(true, _("Column %s does not exist in matrix."), format_and_print(vargs[1]).c_str(), NULL);
151 return 0;
152 }
153 vargs[0].columnToVector(col, mstruct);
154 return 1;
155 }
RowsFunction()156 RowsFunction::RowsFunction() : MathFunction("rows", 1) {
157 setArgumentDefinition(1, new VectorArgument(""));
158 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)159 int RowsFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
160 if(!vargs[0].isMatrix()) mstruct = m_one;
161 else mstruct = (int) vargs[0].rows();
162 return 1;
163 }
ColumnsFunction()164 ColumnsFunction::ColumnsFunction() : MathFunction("columns", 1) {
165 setArgumentDefinition(1, new VectorArgument(""));
166 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)167 int ColumnsFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
168 if(!vargs[0].isMatrix()) mstruct = (int) vargs[0].countChildren();
169 else mstruct = (int) vargs[0].columns();
170 return 1;
171 }
ElementsFunction()172 ElementsFunction::ElementsFunction() : MathFunction("elements", 1) {
173 setArgumentDefinition(1, new VectorArgument(""));
174 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)175 int ElementsFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
176 if(vargs[0].isMatrix()) {
177 mstruct = (int) (vargs[0].rows() * vargs[0].columns());
178 } else {
179 mstruct = (int) vargs[0].countChildren();
180 }
181 return 1;
182 }
ElementFunction()183 ElementFunction::ElementFunction() : MathFunction("element", 2, 3) {
184 setArgumentDefinition(1, new VectorArgument(""));
185 setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE));
186 setArgumentDefinition(3, new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SIZE));
187 setDefaultValue(3, "0");
188 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)189 int ElementFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
190 if(vargs[2].number().isPositive() && vargs[0].isMatrix()) {
191 size_t row = (size_t) vargs[1].number().uintValue();
192 size_t col = (size_t) vargs[2].number().uintValue();
193 bool b = true;
194 if(col > vargs[0].columns()) {
195 CALCULATOR->error(true, _("Column %s does not exist in matrix."), format_and_print(vargs[2]).c_str(), NULL);
196 b = false;
197 }
198 if(row > vargs[0].rows()) {
199 CALCULATOR->error(true, _("Row %s does not exist in matrix."), format_and_print(vargs[1]).c_str(), NULL);
200 b = false;
201 }
202 if(b) {
203 const MathStructure *em = vargs[0].getElement(row, col);
204 if(em) mstruct = *em;
205 else b = false;
206 }
207 return b;
208 } else {
209 if(vargs[2].number().isGreaterThan(1)) {
210 CALCULATOR->error(false, _("Argument 3, %s, is ignored for vectors."), getArgumentDefinition(3)->name().c_str(), NULL);
211 }
212 size_t row = (size_t) vargs[1].number().uintValue();
213 if(row > vargs[0].countChildren()) {
214 CALCULATOR->error(true, _("Element %s does not exist in vector."), format_and_print(vargs[1]).c_str(), NULL);
215 return 0;
216 }
217 mstruct = *vargs[0].getChild(row);
218 return 1;
219 }
220 }
DimensionFunction()221 DimensionFunction::DimensionFunction() : MathFunction("dimension", 1) {
222 setArgumentDefinition(1, new VectorArgument(""));
223 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)224 int DimensionFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
225 mstruct = (int) vargs[0].countChildren();
226 return 1;
227 }
ComponentFunction()228 ComponentFunction::ComponentFunction() : MathFunction("component", 2) {
229 setArgumentDefinition(1, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE));
230 setArgumentDefinition(2, new VectorArgument(""));
231 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)232 int ComponentFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
233 size_t i = (size_t) vargs[0].number().uintValue();
234 if(i > vargs[1].countChildren()) {
235 CALCULATOR->error(true, _("Element %s does not exist in vector."), format_and_print(vargs[0]).c_str(), NULL);
236 return 0;
237 }
238 mstruct = *vargs[1].getChild(i);
239 return 1;
240 }
LimitsFunction()241 LimitsFunction::LimitsFunction() : MathFunction("limits", 3) {
242 setArgumentDefinition(1, new VectorArgument(""));
243 Argument *arg = new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SINT);
244 arg->setHandleVector(false);
245 setArgumentDefinition(2, arg);
246 arg = new IntegerArgument("", ARGUMENT_MIN_MAX_NONE, true, true, INTEGER_TYPE_SINT);
247 arg->setHandleVector(false);
248 setArgumentDefinition(3, arg);
249 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)250 int LimitsFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
251 vargs[0].getRange(vargs[1].number().intValue(), vargs[2].number().intValue(), mstruct);
252 return 1;
253 }
AreaFunction()254 AreaFunction::AreaFunction() : MathFunction("area", 5) {
255 setArgumentDefinition(1, new MatrixArgument(""));
256 Argument *arg = new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE);
257 arg->setHandleVector(false);
258 setArgumentDefinition(2, arg);
259 arg = new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE);
260 arg->setHandleVector(false);
261 setArgumentDefinition(3, arg);
262 arg = new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE);
263 arg->setHandleVector(false);
264 setArgumentDefinition(4, arg);
265 arg = new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE);
266 arg->setHandleVector(false);
267 setArgumentDefinition(5, arg);
268 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)269 int AreaFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
270 vargs[0].getArea(vargs[1].number().uintValue(), vargs[2].number().uintValue(), vargs[3].number().uintValue(), vargs[4].number().uintValue(), mstruct);
271 return 1;
272 }
TransposeFunction()273 TransposeFunction::TransposeFunction() : MathFunction("transpose", 1) {
274 setArgumentDefinition(1, new MatrixArgument());
275 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)276 int TransposeFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
277 mstruct = vargs[0];
278 return mstruct.transposeMatrix();
279 }
IdentityMatrixFunction()280 IdentityMatrixFunction::IdentityMatrixFunction() : MathFunction("identity", 1) {
281 ArgumentSet *arg = new ArgumentSet();
282 arg->addArgument(new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE));
283 MatrixArgument *marg = new MatrixArgument();
284 marg->setSquareDemanded(true);
285 arg->addArgument(marg);
286 setArgumentDefinition(1, arg);
287 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)288 int IdentityMatrixFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
289 if(vargs[0].isMatrix()) {
290 if(vargs[0].rows() != vargs[0].columns()) {
291 return 0;
292 }
293 mstruct.setToIdentityMatrix(vargs[0].size());
294 } else {
295 mstruct.setToIdentityMatrix((size_t) vargs[0].number().uintValue());
296 }
297 return 1;
298 }
DeterminantFunction()299 DeterminantFunction::DeterminantFunction() : MathFunction("det", 1) {
300 MatrixArgument *marg = new MatrixArgument();
301 marg->setSquareDemanded(true);
302 setArgumentDefinition(1, marg);
303 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)304 int DeterminantFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
305 vargs[0].determinant(mstruct, eo);
306 return !mstruct.isUndefined();
307 }
PermanentFunction()308 PermanentFunction::PermanentFunction() : MathFunction("permanent", 1) {
309 MatrixArgument *marg = new MatrixArgument();
310 marg->setSquareDemanded(true);
311 setArgumentDefinition(1, marg);
312 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)313 int PermanentFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
314 vargs[0].permanent(mstruct, eo);
315 return !mstruct.isUndefined();
316 }
CofactorFunction()317 CofactorFunction::CofactorFunction() : MathFunction("cofactor", 3) {
318 setArgumentDefinition(1, new MatrixArgument());
319 setArgumentDefinition(2, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE));
320 setArgumentDefinition(3, new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SIZE));
321 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)322 int CofactorFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
323 vargs[0].cofactor((size_t) vargs[1].number().uintValue(), (size_t) vargs[2].number().uintValue(), mstruct, eo);
324 return !mstruct.isUndefined();
325 }
AdjointFunction()326 AdjointFunction::AdjointFunction() : MathFunction("adj", 1) {
327 MatrixArgument *marg = new MatrixArgument();
328 marg->setSquareDemanded(true);
329 setArgumentDefinition(1, marg);
330 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)331 int AdjointFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
332 mstruct = vargs[0];
333 if(!mstruct.adjointMatrix(eo)) return 0;
334 return !mstruct.isUndefined();
335 }
InverseFunction()336 InverseFunction::InverseFunction() : MathFunction("inverse", 1) {
337 MatrixArgument *marg = new MatrixArgument();
338 marg->setSquareDemanded(true);
339 setArgumentDefinition(1, marg);
340 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)341 int InverseFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
342 mstruct = vargs[0];
343 return mstruct.invertMatrix(eo);
344 }
MagnitudeFunction()345 MagnitudeFunction::MagnitudeFunction() : MathFunction("magnitude", 1) {
346 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)347 int MagnitudeFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
348 mstruct = vargs[0];
349 if(mstruct.isVector()) {
350 mstruct ^= nr_two;
351 mstruct.raise(nr_half);
352 return 1;
353 } else if(mstruct.representsScalar()) {
354 mstruct.transformById(FUNCTION_ID_ABS);
355 return 1;
356 }
357 mstruct.eval(eo);
358 if(mstruct.isVector()) {
359 mstruct ^= nr_two;
360 mstruct.raise(nr_half);
361 return 1;
362 }
363 mstruct = vargs[0];
364 mstruct.transformById(FUNCTION_ID_ABS);
365 return 1;
366 }
HadamardFunction()367 HadamardFunction::HadamardFunction() : MathFunction("hadamard", 1, -1) {
368 setArgumentDefinition(1, new VectorArgument());
369 setArgumentDefinition(2, new VectorArgument());
370 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)371 int HadamardFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
372 bool b_matrix = vargs[0].isMatrix();
373 for(size_t i3 = 1; i3 < vargs.size(); i3++) {
374 if(b_matrix) {
375 if(!vargs[i3].isMatrix() || vargs[i3].columns() != vargs[0].columns() || vargs[i3].rows() != vargs[0].rows()) {
376 CALCULATOR->error(true, _("%s() requires that all matrices/vectors have the same dimensions."), preferredDisplayName().name.c_str(), NULL);
377 return 0;
378 }
379 } else if(vargs[i3].size() != vargs[0].size()) {
380 CALCULATOR->error(true, _("%s() requires that all matrices/vectors have the same dimensions."), preferredDisplayName().name.c_str(), NULL);
381 return 0;
382 }
383 }
384 mstruct = vargs[0];
385 for(size_t i = 0; i < mstruct.size(); i++) {
386 if(b_matrix) {
387 for(size_t i2 = 0; i2 < mstruct[i].size(); i2++) {
388 for(size_t i3 = 1; i3 < vargs.size(); i3++) mstruct[i][i2] *= vargs[i3][i][i2];
389 }
390 } else {
391 for(size_t i3 = 1; i3 < vargs.size(); i3++) mstruct[i] *= vargs[i3][i];
392 }
393 }
394 return 1;
395 }
matrix_to_rref(MathStructure & m,const EvaluationOptions & eo)396 bool matrix_to_rref(MathStructure &m, const EvaluationOptions &eo) {
397 size_t rows = m.rows();
398 size_t cols = m.columns();
399 size_t cur_row = 0;
400 for(size_t c = 0; c < cols; ) {
401 bool b = false;
402 for(size_t r = cur_row; r < rows; r++) {
403 if(m[r][c].representsNonZero()) {
404 if(r != cur_row) {
405 MathStructure *mrow = &m[r];
406 mrow->ref();
407 m.delChild(r + 1);
408 m.insertChild_nocopy(mrow, cur_row + 1);
409 }
410 for(r = 0; r < rows; r++) {
411 if(r != cur_row) {
412 if(m[r][c].representsNonZero()) {
413 MathStructure mmul(m[r][c]);
414 mmul.calculateDivide(m[cur_row][c], eo);
415 mmul.calculateNegate(eo);
416 for(size_t c2 = 0; c2 < cols; c2++) {
417 if(c2 == c) {
418 m[r][c2].clear(true);
419 } else {
420 MathStructure madd(m[cur_row][c2]);
421 madd.calculateMultiply(mmul, eo);
422 m[r][c2].calculateAdd(madd, eo);
423 }
424 }
425 } else if(!m[r][c].isZero()) {
426 return false;
427 }
428 }
429 }
430 for(size_t c2 = 0; c2 < cols; c2++) {
431 if(c2 != c) {
432 m[cur_row][c2].calculateDivide(m[cur_row][c], eo);
433 }
434 }
435 m[cur_row][c].set(1, 1, 0, true);
436 cur_row++;
437 b = true;
438 break;
439 } else if(!m[r][c].isZero()) {
440 return false;
441 }
442 }
443 if(cur_row == rows) break;
444 if(!b) c++;
445 }
446 return true;
447 }
RRefFunction()448 RRefFunction::RRefFunction() : MathFunction("rref", 1) {
449 setArgumentDefinition(1, new MatrixArgument());
450 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)451 int RRefFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
452 // echelon matrix
453 MathStructure m(vargs[0]);
454 if(!matrix_to_rref(m, eo)) return false;
455 mstruct = m;
456 return 1;
457 }
MatrixRankFunction()458 MatrixRankFunction::MatrixRankFunction() : MathFunction("rk", 1) {
459 setArgumentDefinition(1, new MatrixArgument());
460 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)461 int MatrixRankFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
462 MathStructure m(vargs[0]);
463 if(!matrix_to_rref(m, eo)) return false;
464 size_t rows = m.rows();
465 size_t cols = m.columns();
466 Number nr;
467 // count zero rows
468 for(size_t r = 0; r < rows; r++) {
469 bool b = false;
470 for(size_t c = 0; c < cols; c++) {
471 if(m[r][c].representsNonZero()) {
472 b = true;
473 break;
474 } else if(!m[r][c].isZero()) {
475 return false;
476 }
477 }
478 if(!b) break;
479 nr++;
480 }
481 mstruct = nr;
482 return 1;
483 }
EntrywiseFunction()484 EntrywiseFunction::EntrywiseFunction() : MathFunction("entrywise", 2) {
485 VectorArgument *arg = new VectorArgument();
486 arg->addArgument(new VectorArgument());
487 arg->addArgument(new SymbolicArgument());
488 arg->setReoccuringArguments(true);
489 setArgumentDefinition(2, arg);
490 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)491 int EntrywiseFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
492 if(vargs[1].size() == 0) {
493 mstruct = vargs[0];
494 return 1;
495 }
496 bool b_matrix = vargs[1][0].isMatrix();
497 for(size_t i3 = 2; i3 < vargs[1].size(); i3 += 2) {
498 if(b_matrix) {
499 if(!vargs[1][i3].isMatrix() || vargs[1][i3].columns() != vargs[1][0].columns() || vargs[1][i3].rows() != vargs[1][0].rows()) {
500 CALCULATOR->error(true, _("%s() requires that all matrices/vectors have the same dimensions."), preferredDisplayName().name.c_str(), NULL);
501 return 0;
502 }
503 } else if(vargs[1][i3].size() != vargs[1][0].size()) {
504 CALCULATOR->error(true, _("%s() requires that all matrices/vectors have the same dimensions."), preferredDisplayName().name.c_str(), NULL);
505 return 0;
506 }
507 }
508 MathStructure mexpr(vargs[0]);
509 EvaluationOptions eo2 = eo;
510 eo2.calculate_functions = false;
511 mexpr.eval(eo2);
512 mstruct = vargs[1][0];
513 for(size_t i = 0; i < mstruct.size(); i++) {
514 if(b_matrix) {
515 for(size_t i2 = 0; i2 < mstruct[i].size(); i2++) {
516 mstruct[i][i2] = mexpr;
517 for(size_t i3 = 1; i3 < vargs[1].size(); i3 += 2) {
518 mstruct[i][i2].replace(vargs[1][i3], vargs[1][i3 - 1][i][i2]);
519 }
520 }
521 } else {
522 mstruct[i] = mexpr;
523 for(size_t i3 = 1; i3 < vargs[1].size(); i3 += 2) {
524 mstruct[i].replace(vargs[1][i3], vargs[1][i3 - 1][i]);
525 }
526 }
527 }
528 return 1;
529 }
530
531 bool process_replace(MathStructure &mprocess, const MathStructure &mstruct, const MathStructure &vargs, size_t index);
process_replace(MathStructure & mprocess,const MathStructure & mstruct,const MathStructure & vargs,size_t index)532 bool process_replace(MathStructure &mprocess, const MathStructure &mstruct, const MathStructure &vargs, size_t index) {
533 if(mprocess == vargs[1]) {
534 mprocess = mstruct[index];
535 return true;
536 }
537 if(!vargs[3].isEmptySymbol() && mprocess == vargs[3]) {
538 mprocess = (int) index + 1;
539 return true;
540 }
541 if(!vargs[4].isEmptySymbol() && mprocess == vargs[4]) {
542 mprocess = vargs[2];
543 return true;
544 }
545 bool b = false;
546 for(size_t i = 0; i < mprocess.size(); i++) {
547 if(process_replace(mprocess[i], mstruct, vargs, index)) {
548 mprocess.childUpdated(i + 1);
549 b = true;
550 }
551 }
552 return b;
553 }
554
ProcessFunction()555 ProcessFunction::ProcessFunction() : MathFunction("process", 3, 5) {
556 setArgumentDefinition(2, new SymbolicArgument());
557 setArgumentDefinition(3, new VectorArgument());
558 setArgumentDefinition(4, new SymbolicArgument());
559 setDefaultValue(4, "\"\"");
560 setArgumentDefinition(5, new SymbolicArgument());
561 setDefaultValue(5, "\"\"");
562 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)563 int ProcessFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
564
565 mstruct = vargs[2];
566 MathStructure mprocess;
567 for(size_t index = 0; index < mstruct.size(); index++) {
568 mprocess = vargs[0];
569 process_replace(mprocess, mstruct, vargs, index);
570 mstruct[index] = mprocess;
571 }
572 return 1;
573
574 }
575
576
577 bool process_matrix_replace(MathStructure &mprocess, const MathStructure &mstruct, const MathStructure &vargs, size_t rindex, size_t cindex);
process_matrix_replace(MathStructure & mprocess,const MathStructure & mstruct,const MathStructure & vargs,size_t rindex,size_t cindex)578 bool process_matrix_replace(MathStructure &mprocess, const MathStructure &mstruct, const MathStructure &vargs, size_t rindex, size_t cindex) {
579 if(mprocess == vargs[1]) {
580 mprocess = mstruct[rindex][cindex];
581 return true;
582 }
583 if(!vargs[3].isEmptySymbol() && mprocess == vargs[3]) {
584 mprocess = (int) rindex + 1;
585 return true;
586 }
587 if(!vargs[4].isEmptySymbol() && mprocess == vargs[4]) {
588 mprocess = (int) cindex + 1;
589 return true;
590 }
591 if(!vargs[5].isEmptySymbol() && mprocess == vargs[5]) {
592 mprocess = vargs[2];
593 return true;
594 }
595 bool b = false;
596 for(size_t i = 0; i < mprocess.size(); i++) {
597 if(process_matrix_replace(mprocess[i], mstruct, vargs, rindex, cindex)) {
598 mprocess.childUpdated(i + 1);
599 b = true;
600 }
601 }
602 return b;
603 }
604
ProcessMatrixFunction()605 ProcessMatrixFunction::ProcessMatrixFunction() : MathFunction("processm", 3, 6) {
606 setArgumentDefinition(2, new SymbolicArgument());
607 setArgumentDefinition(3, new MatrixArgument());
608 setArgumentDefinition(4, new SymbolicArgument());
609 setDefaultValue(4, "\"\"");
610 setArgumentDefinition(5, new SymbolicArgument());
611 setDefaultValue(5, "\"\"");
612 setArgumentDefinition(6, new SymbolicArgument());
613 setDefaultValue(6, "\"\"");
614 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)615 int ProcessMatrixFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
616
617 mstruct = vargs[2];
618 MathStructure mprocess;
619 for(size_t rindex = 0; rindex < mstruct.size(); rindex++) {
620 for(size_t cindex = 0; cindex < mstruct[rindex].size(); cindex++) {
621 if(CALCULATOR->aborted()) return 0;
622 mprocess = vargs[0];
623 process_matrix_replace(mprocess, mstruct, vargs, rindex, cindex);
624 mstruct[rindex][cindex] = mprocess;
625 }
626 }
627 return 1;
628
629 }
GenerateVectorFunction()630 GenerateVectorFunction::GenerateVectorFunction() : MathFunction("genvector", 4, 6) {
631 setArgumentDefinition(5, new SymbolicArgument());
632 setDefaultValue(5, "undefined");
633 setArgumentDefinition(6, new BooleanArgument());
634 setDefaultValue(6, "0");
635 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)636 int GenerateVectorFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
637 if(CALCULATOR->aborted()) return 0;
638 if(vargs[5].number().getBoolean()) {
639 mstruct = vargs[0].generateVector(vargs[4], vargs[1], vargs[2], vargs[3], NULL, eo);
640 } else {
641 bool overflow = false;
642 int steps = vargs[3].number().intValue(&overflow);
643 if(!vargs[3].isNumber() || overflow || steps < 1) {
644 CALCULATOR->error(true, _("The number of requested elements in generate vector function must be a positive integer."), NULL);
645 return 0;
646 }
647 mstruct = vargs[0].generateVector(vargs[4], vargs[1], vargs[2], steps, NULL, eo);
648 }
649 if(CALCULATOR->aborted()) return 0;
650 return 1;
651 }
SelectFunction()652 SelectFunction::SelectFunction() : MathFunction("select", 2, 4) {
653 setArgumentDefinition(3, new SymbolicArgument());
654 setDefaultValue(3, "undefined");
655 setArgumentDefinition(4, new BooleanArgument());
656 setDefaultValue(4, "0");
657 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions & eo)658 int SelectFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions &eo) {
659 MathStructure mtest;
660 mstruct = vargs[0];
661 mstruct.eval(eo);
662 if(!mstruct.isVector()) {
663 mtest = vargs[1];
664 mtest.replace(vargs[2], mstruct);
665 mtest.eval(eo);
666 if(!mtest.isNumber() || mtest.number().getBoolean() < 0) {
667 CALCULATOR->error(true, _("Comparison failed."), NULL);
668 return -1;
669 }
670 if(mtest.number().getBoolean() == 0) {
671 if(vargs[3].number().getBoolean() > 0) {
672 CALCULATOR->error(true, _("No matching item found."), NULL);
673 return -1;
674 }
675 mstruct.clearVector();
676 }
677 return 1;
678 }
679 for(size_t i = 0; i < mstruct.size();) {
680 mtest = vargs[1];
681 mtest.replace(vargs[2], mstruct[i]);
682 mtest.eval(eo);
683 if(!mtest.isNumber() || mtest.number().getBoolean() < 0) {
684 CALCULATOR->error(true, _("Comparison failed."), NULL);
685 return -1;
686 }
687 if(mtest.number().getBoolean() == 0) {
688 if(vargs[3].number().getBoolean() == 0) {
689 mstruct.delChild(i + 1);
690 } else {
691 i++;
692 }
693 } else if(vargs[3].number().getBoolean() > 0) {
694 MathStructure msave(mstruct[i]);
695 mstruct = msave;
696 return 1;
697 } else {
698 i++;
699 }
700 }
701 if(vargs[3].number().getBoolean() > 0) {
702 CALCULATOR->error(true, _("No matching item found."), NULL);
703 return -1;
704 }
705 return 1;
706 }
LoadFunction()707 LoadFunction::LoadFunction() : MathFunction("load", 1, 3) {
708 setArgumentDefinition(1, new FileArgument());
709 Argument *arg = new IntegerArgument("", ARGUMENT_MIN_MAX_POSITIVE, true, true, INTEGER_TYPE_SINT);
710 arg->setHandleVector(false);
711 setArgumentDefinition(2, arg);
712 setDefaultValue(2, "1");
713 setArgumentDefinition(3, new TextArgument());
714 setDefaultValue(3, "\",\"");
715 }
calculate(MathStructure & mstruct,const MathStructure & vargs,const EvaluationOptions &)716 int LoadFunction::calculate(MathStructure &mstruct, const MathStructure &vargs, const EvaluationOptions&) {
717 string delim = vargs[2].symbol();
718 if(delim == "tab") {
719 delim = "\t";
720 }
721 if(!CALCULATOR->importCSV(mstruct, vargs[0].symbol().c_str(), vargs[1].number().intValue(), delim)) {
722 CALCULATOR->error(true, "Failed to load %s.", vargs[0].symbol().c_str(), NULL);
723 return 0;
724 }
725 return 1;
726 }
ExportFunction()727 ExportFunction::ExportFunction() : MathFunction("export", 2, 3) {
728 setArgumentDefinition(1, new VectorArgument());
729 setArgumentDefinition(2, new FileArgument());
730 setArgumentDefinition(3, new TextArgument());
731 setDefaultValue(3, "\",\"");
732 }
calculate(MathStructure &,const MathStructure & vargs,const EvaluationOptions &)733 int ExportFunction::calculate(MathStructure&, const MathStructure &vargs, const EvaluationOptions&) {
734 string delim = vargs[2].symbol();
735 if(delim == "tab") {
736 delim = "\t";
737 }
738 if(!CALCULATOR->exportCSV(vargs[0], vargs[1].symbol().c_str(), delim)) {
739 CALCULATOR->error(true, "Failed to export to %s.", vargs[1].symbol().c_str(), NULL);
740 return 0;
741 }
742 return 1;
743 }
744
745