NumeRe v1.1.4
NumeRe: Framework für Numerische Rechnungen
matrixoperations.cpp
Go to the documentation of this file.
1/*****************************************************************************
2 NumeRe: Framework fuer Numerische Rechnungen
3 Copyright (C) 2015 Erik Haenel et al.
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17******************************************************************************/
18#include <Eigen/Dense>
19
20#include "matrixoperations.hpp"
21#include "matfuncs.hpp"
22#include "parser_functions.hpp"
23#include "../../kernel.hpp"
24#include "../utils/stringtools.hpp"
25#include "../io/logger.hpp"
26#include <list>
27#include <cmath>
28
29#define EIGENVALUES 0
30#define EIGENVECTORS 1
31#define DIAGONALIZE 2
32
34{
35 // Returned values
36 std::vector<Matrix> vReturnedMatrices;
37
38 // Cached tables or clusters
39 // Structure definition
41 {
42 std::string sName;
45 };
46
47 // Actual cache
48 std::vector<MatOpDataAccess> vDataAccesses;
49};
50
51using namespace std;
52
53static Matrix evalMatOp(string& sCmd, Parser& _parser, MemoryManager& _data, FunctionDefinitionManager& _functions, const Settings& _option, MatOpCache& _cache);
54static size_t getPrevMatMultiOp(const string& sCmd, size_t nLastPos);
55static Matrix multiplyMatrices(const Matrix& _mLeft, const Matrix& _mRight, const string& sCmd, const string& sExpr, size_t position);
56static Matrix getMatrixElements(string& sExpr, const Matrix& _mMatrix, Parser& _parser, MemoryManager& _data, FunctionDefinitionManager& _functions, const Settings& _option);
57static vector<mu::value_type> calcDeltasForMatFill(const std::vector<std::vector<mu::value_type>>& _mMatrix, unsigned int nLine);
58static void showMatrixResult(const Matrix& _mResult, const Settings& _option);
59static Indices getIndicesForMatrix(const string& sCmd, const MatOpCache& _cache, Parser& _parser, MemoryManager& _data, const Settings& _option);
60static bool containsMatrices(const string& sExpr, MemoryManager& _data);
61
62Matrix transposeMatrix(const Matrix& _mMatrix);
63Matrix createZeroesMatrix(unsigned int nLines, unsigned int nCols);
64
65static Matrix createMatFromCols(string& sCmd, Parser& _parser, MemoryManager& _data, FunctionDefinitionManager& _functions, const Settings& _option);
66static Matrix createMatFromColsFilled(string& sCmd, Parser& _parser, MemoryManager& _data, FunctionDefinitionManager& _functions, const Settings& _option);
67static Matrix createMatFromLines(string& sCmd, Parser& _parser, MemoryManager& _data, FunctionDefinitionManager& _functions, const Settings& _option);
68static Matrix createMatFromLinesFilled(string& sCmd, Parser& _parser, MemoryManager& _data, FunctionDefinitionManager& _functions, const Settings& _option);
69
70
71
72
73
86bool performMatrixOperation(string& sCmd, Parser& _parser, MemoryManager& _data, FunctionDefinitionManager& _functions, const Settings& _option)
87{
88 // Create the cache
89 MatOpCache _cache;
90 string sTargetName = "";
91 Indices _idx;
92
93 bool bAllowMatrixClearing = false;
94 bool isCluster = false;
95
96 // Kommando entfernen
97 if (findCommand(sCmd).sString == "matop")
98 sCmd.erase(0, findCommand(sCmd).nPos+5);
99
100 if (findCommand(sCmd).sString == "mtrxop")
101 sCmd.erase(0, findCommand(sCmd).nPos+6);
102
103 if (!_functions.call(sCmd))
105
106 // Ensure that there's at least a single
107 // matrix operation available
108 if (!containsMatrices(sCmd, _data))
110
111 // Rekursive Ausdruecke ersetzen
113
114 // Target identifizieren
115 if (sCmd.find('=') != string::npos
116 && sCmd.find('=')
117 && sCmd[sCmd.find('=')+1] != '='
118 && sCmd[sCmd.find('=')-1] != '!'
119 && sCmd[sCmd.find('=')-1] != '<'
120 && sCmd[sCmd.find('=')-1] != '>'
121 && sCmd.substr(0, sCmd.find('=')).find_first_of("({") != string::npos
122 && sCmd[sCmd.find_first_not_of(' ')] != '{')
123 {
124 sTargetName = sCmd.substr(0, sCmd.find('='));
125 StripSpaces(sTargetName);
126 size_t parens = sTargetName.find_first_of("({");
127
128 if (parens == string::npos)
129 throw SyntaxError(SyntaxError::INVALID_DATA_ACCESS, sCmd, sTargetName, sTargetName);
130
131 // Distinguish between tables and clusters
132 if (sTargetName[parens] == '(')
133 {
134 // Create a new table
135 if (!_data.isTable(sTargetName))
136 _data.addTable(sTargetName.substr(0, parens), _option);
137
138 if (sTargetName.substr(sTargetName.find('('),2) == "()")
139 {
140 bAllowMatrixClearing = true;
143 }
144 }
145 else if (sTargetName[parens] == '{')
146 {
147 // Create a new cluster
148 if (!_data.isCluster(sTargetName))
149 _data.newCluster(sTargetName);
150
151 isCluster = true;
152
153 if (sTargetName.substr(sTargetName.find('{'),2) == "{}")
154 {
155 bAllowMatrixClearing = true;
158 }
159 }
160
161 if (!bAllowMatrixClearing)
162 getIndices(sTargetName, _idx, _parser, _data, _option);
163
164 if (!isValidIndexSet(_idx))
165 throw SyntaxError(SyntaxError::INVALID_INDEX, sCmd, sTargetName, _idx.row.to_string() + ", " + _idx.col.to_string());
166
167 sCmd.erase(0, sCmd.find('=')+1);
168
169 sTargetName.erase(sTargetName.find_first_of("({"));
170 }
171 else
172 {
173 sTargetName = "matrix";
176
177 if (!_data.isTable("matrix("))
178 _data.addTable("matrix", _option);
179 else
180 bAllowMatrixClearing = true;
181 }
182
183 g_logger.debug("Start evalMatOp.");
184 // Matrixmultiplikationen / Transpositionen / Invertierungen?
185 // -> Submatrixoperationen ausfuehren
186 Matrix _mResult = evalMatOp(sCmd, _parser, _data, _functions, _option, _cache);
187 g_logger.debug("Stop evalMatOp.");
189
190 // Safety check
191 if (_mResult.isEmpty())
192 return false;
193
194 // Target in Zielmatrix speichern
195 if (!isCluster)
196 {
197 // This target is a table
198 if (bAllowMatrixClearing)
199 _data.deleteBulk(sTargetName, 0, _data.getLines(sTargetName, false) - 1, 0, _data.getCols(sTargetName, false) - 1);
200
201 // Prepare the target size
202 _data.resizeTable(_idx.col.front()+_mResult.cols(), sTargetName);
203 Memory* _table = _data.getTable(sTargetName);
204
205 int maxrow = _idx.row.subidx(0, _mResult.rows()).max();
206
207 for (size_t j = 0; j < _mResult.cols(); j++)
208 {
209 if (_idx.col[j] == VectorIndex::INVALID)
210 break;
211
212 _table->writeData(maxrow, _idx.col[j], 0.0);
213 }
214
215 // Write the contents to the table
216 #pragma omp parallel for
217 for (unsigned int j = 0; j < _mResult.cols(); j++)
218 {
219 if (_idx.col[j] == VectorIndex::INVALID)
220 continue;
221
222 for (unsigned int i = 0; i < _mResult.rows(); i++)
223 {
224 if (_idx.row[i] == VectorIndex::INVALID)
225 break;
226
227 _table->writeDataDirectUnsafe(_idx.row[i], _idx.col[j], _mResult(i, j));
228 }
229 }
230
231 _table->markModified();
232 }
233 else
234 {
235 // This target is a cluster, get a reference to it
236 NumeRe::Cluster& cluster = _data.getCluster(sTargetName);
237
238 if (bAllowMatrixClearing)
239 cluster.clear();
240
241 // Assign either the first column or the first line
242 if (_mResult.rows() == 1)
243 {
244 // Assign the first line
245 for (size_t i = 0; i < _mResult.cols(); i++)
246 {
247 if (_idx.row[i] == VectorIndex::INVALID)
248 break;
249
250 cluster.setDouble(_idx.row[i], _mResult(0, i));
251 }
252 }
253 else
254 {
255 // Assign the first column
256 for (size_t i = 0; i < _mResult.rows(); i++)
257 {
258 if (_idx.row[i] == VectorIndex::INVALID)
259 break;
260
261 cluster.setDouble(_idx.row[i], _mResult(i));
262 }
263 }
264 }
265
266 // Display the result in the terminal
267 showMatrixResult(_mResult, _option);
268
269 return true;
270}
271
272
286static Matrix evalMatOp(string& sCmd, Parser& _parser, MemoryManager& _data, FunctionDefinitionManager& _functions, const Settings& _option, MatOpCache& _cache)
287{
288 string __sCmd;
289 size_t pos_back = 0;
290 size_t iter_start = 0;
291
292 mu::value_type* v = 0;
293 int nResults = 0;
294 static std::map<std::string, MatFuncDef> mMatrixFunctions = getMatrixFunctions();
295
296 // Check, whether there's a target vector available in this expression part
297 size_t nEqPos = sCmd.find('=');
298
299 if (nEqPos != string::npos
300 && nEqPos
301 && sCmd[nEqPos+1] != '='
302 && sCmd[nEqPos-1] != '!'
303 && sCmd[nEqPos-1] != '<'
304 && sCmd[nEqPos-1] != '>'
305 && sCmd.substr(0, nEqPos).find('{') != string::npos)
306 {
307 iter_start = nEqPos+1;
308 }
309
310 // Apply all known and requested matrix functions.
311 // The equation will be segmentized and the evaluated
312 // part will be appended to the evaluated equation.
313 for (unsigned int i = iter_start; i < sCmd.length(); i++)
314 {
315 size_t nMatchingParens;
316 // Is the current character alphabetical and
317 // either the first or prefixed with a delimiter?
318 // Then this is a possible start for a function
319 if ((!i || isDelimiter(sCmd[i-1])) && (isalpha(sCmd[i]) || sCmd[i] == '{'))
320 {
321 for (auto fIter = mMatrixFunctions.begin(); fIter != mMatrixFunctions.end(); ++fIter)
322 {
323 if (fIter->second.signature == MATSIG_INVALID)
324 continue;
325
326 if (StringView(sCmd, i, fIter->first.length()+1) == fIter->first + "("
327 && (nMatchingParens = getMatchingParenthesis(StringView(sCmd, i+fIter->first.length()))) != string::npos)
328 {
329 // Extract argument
330 std::string sSubExpr = sCmd.substr(i+fIter->first.length()+1, nMatchingParens-1);
331
332 // Create the error structure
333 MatFuncErrorInfo errorInfo(sCmd, sSubExpr, i+fIter->first.length());
334
335 // Handle the signatures and
336 // perform the recursions
337 switch (fIter->second.signature)
338 {
339 case MATSIG_INVALID:
340 break; // Just to avoid compiler warnings
341 case MATSIG_MAT:
342 {
343 _cache.vReturnedMatrices.push_back(fIter->second.func(MatFuncData(evalMatOp(sSubExpr, _parser, _data, _functions, _option, _cache)), errorInfo));
344 break;
345 }
346 case MATSIG_MAT_NOPT:
347 {
348 std::string sMatrix = getNextArgument(sSubExpr, true);
349 int n = 0;
350
351 if (sSubExpr.length())
352 {
353 _parser.SetExpr(sSubExpr);
354 v = _parser.Eval(nResults);
355 n = intCast(v[0]);
356 }
357
358 _cache.vReturnedMatrices.push_back(fIter->second.func(MatFuncData(evalMatOp(sMatrix, _parser, _data, _functions, _option, _cache), n), errorInfo));
359 break;
360 }
361 case MATSIG_MAT_MAT:
362 {
363 std::string sMatrix1 = getNextArgument(sSubExpr, true);
364 _cache.vReturnedMatrices.push_back(fIter->second.func(MatFuncData(evalMatOp(sMatrix1, _parser, _data, _functions, _option, _cache), evalMatOp(sSubExpr, _parser, _data, _functions, _option, _cache)), errorInfo));
365 break;
366 }
368 {
369 std::string sMatrix1 = getNextArgument(sSubExpr, true);
370 std::string sMatrix2 = getNextArgument(sSubExpr, true);
371 _cache.vReturnedMatrices.push_back(fIter->second.func(MatFuncData(evalMatOp(sMatrix1, _parser, _data, _functions, _option, _cache), evalMatOp(sMatrix2, _parser, _data, _functions, _option, _cache), evalMatOp(sSubExpr, _parser, _data, _functions, _option, _cache)), errorInfo));
372 break;
373 }
374 case MATSIG_MAT_MAT_N:
375 {
376 std::string sMatrix1 = getNextArgument(sSubExpr, true);
377 std::string sMatrix2 = getNextArgument(sSubExpr, true);
378 _parser.SetExpr(sSubExpr);
379 v = _parser.Eval(nResults);
380 int n = intCast(v[0]); // int n = nResults > 1 ? intCast(v[1]) : 0;
381 _cache.vReturnedMatrices.push_back(fIter->second.func(MatFuncData(evalMatOp(sMatrix1, _parser, _data, _functions, _option, _cache), evalMatOp(sMatrix2, _parser, _data, _functions, _option, _cache), n), errorInfo));
382 break;
383 }
384 case MATSIG_MAT_F:
385 {
386 std::string sMatrix = getNextArgument(sSubExpr, true);
387
388 _parser.SetExpr(sSubExpr);
389 v = _parser.Eval(nResults);
390 mu::value_type fVal = v[0];
391
392 _cache.vReturnedMatrices.push_back(fIter->second.func(MatFuncData(evalMatOp(sMatrix, _parser, _data, _functions, _option, _cache), fVal), errorInfo));
393 break;
394 }
395 case MATSIG_MAT_F_N:
396 {
397 std::string sMatrix = getNextArgument(sSubExpr, true);
398
399 _parser.SetExpr(sSubExpr);
400 v = _parser.Eval(nResults);
401 mu::value_type fVal = v[0];
402 int n = nResults > 1 ? intCast(v[1]) : 0;
403
404 _cache.vReturnedMatrices.push_back(fIter->second.func(MatFuncData(evalMatOp(sMatrix, _parser, _data, _functions, _option, _cache), fVal, n), errorInfo));
405 break;
406 }
408 {
409 std::string sMatrix = getNextArgument(sSubExpr, true);
410
411 _parser.SetExpr(sSubExpr);
412 v = _parser.Eval(nResults);
413 int n = intCast(v[0]);
414 int m = intCast(v[0]);
415
416 if (nResults > 1)
417 m = intCast(v[1]);
418
419 _cache.vReturnedMatrices.push_back(fIter->second.func(MatFuncData(evalMatOp(sMatrix, _parser, _data, _functions, _option, _cache), n, m), errorInfo));
420 break;
421 }
422 case MATSIG_N_MOPT:
423 {
424 _parser.SetExpr(sSubExpr);
425 v = _parser.Eval(nResults);
426
427 if (nResults > 1)
428 _cache.vReturnedMatrices.push_back(fIter->second.func(MatFuncData(intCast(v[0]), intCast(v[1])), errorInfo));
429 else
430 _cache.vReturnedMatrices.push_back(fIter->second.func(MatFuncData(intCast(v[0])), errorInfo));
431
432 break;
433 }
434 }
435
436 // Prepare leading part of the equation
437 __sCmd += sCmd.substr(pos_back, i-pos_back);
438
439 // Store the last position and advance the
440 // current position
441 pos_back = i+nMatchingParens+fIter->first.length()+1;
442 i = pos_back-1;
443
444 // append the returned matrix
445 __sCmd += "_~returnedMatrix["+toString((int)_cache.vReturnedMatrices.size()-1)+"]";
446 }
447 }
448
449 // construct matrix from columns -> MAT(...)
450 if (sCmd.substr(i,6) == "matfc("
451 && (nMatchingParens = getMatchingParenthesis(StringView(sCmd, i+5))) != string::npos)
452 {
453 string sSubExpr = sCmd.substr(i+6, nMatchingParens-1);
454 __sCmd += sCmd.substr(pos_back, i-pos_back);
455 _cache.vReturnedMatrices.push_back(createMatFromCols(sSubExpr, _parser, _data, _functions, _option));
456 pos_back = i+nMatchingParens+6;
457 __sCmd += "_~returnedMatrix["+toString((int)_cache.vReturnedMatrices.size()-1)+"]";
458 i = pos_back-1;
459 }
460
461 // construct matrix from lines -> MAT(...)
462 if (sCmd.substr(i,6) == "matfl("
463 && (nMatchingParens = getMatchingParenthesis(StringView(sCmd, i+5))) != string::npos)
464 {
465 string sSubExpr = sCmd.substr(i+6, nMatchingParens-1);
466 __sCmd += sCmd.substr(pos_back, i-pos_back);
467 _cache.vReturnedMatrices.push_back(createMatFromLines(sSubExpr, _parser, _data, _functions, _option));
468 pos_back = i+nMatchingParens+6;
469 __sCmd += "_~returnedMatrix["+toString((int)_cache.vReturnedMatrices.size()-1)+"]";
470 i = pos_back-1;
471 }
472
473 // construct matrix from columns and fill missing values -> MAT(...)
474 if (sCmd.substr(i,7) == "matfcf("
475 && (nMatchingParens = getMatchingParenthesis(StringView(sCmd, i+6))) != string::npos)
476 {
477 string sSubExpr = sCmd.substr(i+7, nMatchingParens-1);
478 __sCmd += sCmd.substr(pos_back, i-pos_back);
479 _cache.vReturnedMatrices.push_back(createMatFromColsFilled(sSubExpr, _parser, _data, _functions, _option));
480 pos_back = i+nMatchingParens+7;
481 __sCmd += "_~returnedMatrix["+toString((int)_cache.vReturnedMatrices.size()-1)+"]";
482 i = pos_back-1;
483 }
484
485 // construct matrix from lines and fill missing values -> MAT(...)
486 if (sCmd.substr(i,7) == "matflf("
487 && (nMatchingParens = getMatchingParenthesis(StringView(sCmd, i+6))) != string::npos)
488 {
489 string sSubExpr = sCmd.substr(i+7, nMatchingParens-1);
490 __sCmd += sCmd.substr(pos_back, i-pos_back);
491 _cache.vReturnedMatrices.push_back(createMatFromLinesFilled(sSubExpr, _parser, _data, _functions, _option));
492 pos_back = i+nMatchingParens+7;
493 __sCmd += "_~returnedMatrix["+toString((int)_cache.vReturnedMatrices.size()-1)+"]";
494 i = pos_back-1;
495 }
496
497 // Handle old vector syntax (will most probably be changed to matrix syntax)
498 if (sCmd.substr(i,2) == "{{"
499 && (nMatchingParens = getMatchingParenthesis(StringView(sCmd, i))) != string::npos)
500 {
501 string sSubExpr = sCmd.substr(i+1, nMatchingParens-1);
502 __sCmd += sCmd.substr(pos_back, i-pos_back);
503 _cache.vReturnedMatrices.push_back(createMatFromCols(sSubExpr, _parser, _data, _functions, _option));
504 pos_back = i+nMatchingParens+1;
505 __sCmd += "_~returnedMatrix["+toString((int)_cache.vReturnedMatrices.size()-1)+"]";
506 i = pos_back-1;
507 }
508
509 // Handle vectors
510 if (sCmd[i] == '{'
511 && (nMatchingParens = getMatchingParenthesis(StringView(sCmd, i))) != string::npos)
512 {
513 string sSubExpr = sCmd.substr(i, nMatchingParens+1);
514 __sCmd += sCmd.substr(pos_back, i-pos_back);
515 _cache.vReturnedMatrices.push_back(createMatFromCols(sSubExpr, _parser, _data, _functions, _option));
516 pos_back = i+nMatchingParens+1;
517 __sCmd += "_~returnedMatrix["+toString((int)_cache.vReturnedMatrices.size()-1)+"]";
518 i = pos_back-1;
519 }
520 }
521
522 // Handle index selectors after a matrix function
523 if (i > 14
524 && sCmd[i] == '('
525 && i == pos_back // only true, if the last iteration evaluated a subexpression
526 && sCmd.find_last_not_of(' ',i-1) != string::npos
527 && (__sCmd.back() == ']' || __sCmd.back() == ')')) //...returnedMatrix[N](:,:)
528 {
529 int nMatrix = 0;
530 nMatrix = StrToInt(__sCmd.substr(__sCmd.rfind('[')+1, __sCmd.rfind(']')-__sCmd.rfind('[')-1));
531 if (__sCmd.substr(__sCmd.rfind('[')-16,17) == "_~returnedMatrix[")
532 {
533 nMatchingParens = getMatchingParenthesis(StringView(sCmd, i));
534 string sSubExpr = sCmd.substr(i, nMatchingParens+1);
535 pos_back = i+nMatchingParens+1;
536 _cache.vReturnedMatrices[nMatrix] = getMatrixElements(sSubExpr, _cache.vReturnedMatrices[nMatrix], _parser, _data, _functions, _option);
537 i = pos_back-1;
538 }
539 }
540
541 // Pre-evaluate parentheses
542 if (sCmd[i] == '(')
543 {
544 nMatchingParens = getMatchingParenthesis(StringView(sCmd, i));
545 //size_t nLastDelimiter;
546
547 if (sCmd.substr(i, nMatchingParens).find("**") != string::npos
548 || (sCmd.length() > i+nMatchingParens+1 && sCmd[i+nMatchingParens+1] == '('))
549 // Removed this due to unnecessary double evaluation (might be necessary tough!)
550 /*|| (i > 1
551 && (nLastDelimiter = sCmd.find_last_of(" /+-*!^%&|#(){}?:,<>=", i-1)) != std::string::npos
552 && !_data.isTable(sCmd.substr(nLastDelimiter+1, i-nLastDelimiter-1))))*/
553 {
554 string sSubExpr = sCmd.substr(i+1, nMatchingParens-1);
555 size_t closing_par_pos = i+nMatchingParens;
556
557 if (sCmd.length() > closing_par_pos+1 && sCmd[closing_par_pos+1] == '(')
558 {
559 if (i && (isalnum(sCmd[i-1]) || sCmd[i-1] == '_'))
560 {
561 for (int j = i-1; j >= 0; j--)
562 {
563 if ((j && !isalnum(sCmd[j-1]) && sCmd[j-1] != '_') || !j)
564 {
565 __sCmd += sCmd.substr(pos_back, j-pos_back);
566 sSubExpr = sCmd.substr(j, closing_par_pos+1 - j);
567 break;
568 }
569 }
570 }
571 else
572 __sCmd += sCmd.substr(pos_back, i-pos_back);
573
574 _cache.vReturnedMatrices.push_back(evalMatOp(sSubExpr, _parser, _data, _functions, _option, _cache));
575 __sCmd += "_~returnedMatrix["+toString((int)_cache.vReturnedMatrices.size()-1)+"]";
576 }
577 else
578 {
579 __sCmd += sCmd.substr(pos_back, i-pos_back);
580 __sCmd += "(";
581
582 // As this might be a usual function, evaluate each argument
583 // separately (if it is matrix expression) and combine them
584 // afterwards
585 while (sSubExpr.length())
586 {
587 string sExpr = getNextArgument(sSubExpr, true);
588
589 if (containsMatrices(sExpr, _data))
590 {
591 _cache.vReturnedMatrices.push_back(evalMatOp(sExpr, _parser, _data, _functions, _option, _cache));
592 __sCmd += "_~returnedMatrix["+toString((int)_cache.vReturnedMatrices.size()-1)+"]";
593 }
594 else
595 __sCmd += sExpr;
596
597 if (sSubExpr.length())
598 __sCmd += ",";
599 }
600
601 __sCmd += ")";
602 }
603
604 pos_back = closing_par_pos+1;
605 i = pos_back-1;
606 }
607 }
608 }
609
610 // Append the missing part of the equation
611 if (pos_back < sCmd.length())
612 __sCmd += sCmd.substr(pos_back);
613
614 unsigned int nPos = 0;
615
616 // Get the indices of the calls to the memory objects
617 // all caches
618 for (auto iter = _data.getTableMap().begin(); iter != _data.getTableMap().end(); ++iter)
619 {
620 nPos = 0;
621
622 while ((nPos = __sCmd.find(iter->first+"(", nPos)) != string::npos)
623 {
624 // Check the delimiters
625 if (nPos && !isDelimiter(__sCmd[nPos-1]))
626 {
627 nPos++;
628 continue;
629 }
630
632
633 // Get the indices
634 _access.idx = getIndicesForMatrix(__sCmd.substr(nPos), _cache, _parser, _data, _option);
635
636 // Evaluate the indices
637 if (!evaluateIndices(iter->first, _access.idx, _data))
639
640 // Store the name of the current data object
641 _access.sName = iter->first;
642
643 // Identify, which value to use for a missing value
644 if (addMissingVectorComponent("", __sCmd.substr(0,nPos), __sCmd.substr(nPos+1+(iter->first).length()+getMatchingParenthesis(__sCmd.substr(nPos+(iter->first).length()))),false) == "0")
645 _access.missingValues = 0;
646 else
647 _access.missingValues = 1;
648
649 // Add the cached access
650 _cache.vDataAccesses.push_back(_access);
651
652 // Replace the current call with a standardized one
653 __sCmd.replace(nPos, getMatchingParenthesis(__sCmd.substr(nPos+(iter->first).length()))+(iter->first).length()+1, "_~matrix["+toString((int)_cache.vDataAccesses.size()-1)+"]");
654 }
655 }
656
657 // now all clusters
658 for (auto iter = _data.getClusterMap().begin(); iter != _data.getClusterMap().end(); ++iter)
659 {
660 nPos = 0;
661
662 while ((nPos = __sCmd.find(iter->first+"{", nPos)) != string::npos)
663 {
664 // Check the delimiters
665 if (nPos && !isDelimiter(__sCmd[nPos-1]))
666 {
667 nPos++;
668 continue;
669 }
670
671 // Get the indices
672 Indices _idx = getIndicesForMatrix(__sCmd.substr(nPos), _cache, _parser, _data, _option);
673
674 if (_idx.row.isOpenEnd())
675 _idx.row.setRange(0, iter->second.size()-1);
676
677 // Prepare a target matrix
678 Matrix _mClusterMatrix = createZeroesMatrix(_idx.row.size(), 1);
679
680 // Write the contents to the matrix
681 for (size_t i = 0; i < _idx.row.size(); i++)
682 {
683 _mClusterMatrix(i) = iter->second.getDouble(_idx.row[i]);
684 }
685
686 // Declare the cluster as a returned matrix (simplifies the
687 // access logic further down)
688 _cache.vReturnedMatrices.push_back(_mClusterMatrix);
689
690 // Replace the current call with a standardized one
691 __sCmd.replace(nPos, getMatchingParenthesis(__sCmd.substr(nPos+(iter->first).length()))+(iter->first).length()+1,
692 "_~returnedMatrix["+toString((int)_cache.vReturnedMatrices.size()-1)+"]");
693 }
694 }
695
696 pos_back = sCmd.length();
697
698 // Apply the matrix multiplication
699 if (__sCmd.find("**") != string::npos)
700 {
701 // Matrix multiplication is right handed
702 // -> start from the end of the expression
703 for (int n = __sCmd.length()-1; n >= 0; n--)
704 {
705 // Theres's a matrix multiplication
706 if (__sCmd.substr(n, 2) == "**")
707 {
708 // Find the last operator
709 pos_back = getPrevMatMultiOp(sCmd, pos_back)-1;
710 Matrix _mLeft;
711 Matrix _mRight;
712 unsigned int nPositions[2];
713 nPositions[1] = __sCmd.find(']',n)+1;
714 string sElement = __sCmd.substr(__sCmd.find_first_not_of(' ', n+2));
715
716 // Right handed matrix expression
717 size_t p;
718
719 for (size_t i = 0; i < sElement.length(); i++)
720 {
721 if ((sElement[i] == '(' || sElement[i] == '{' || sElement[i] == '[')
722 && (p = getMatchingParenthesis(StringView(sElement, i))) != std::string::npos)
723 i += p+1;
724
725 if (!isalnum(sElement[i]) && sElement[i] != '_' && sElement[i] != '~')
726 {
727 std::string sSubExpr = sElement.substr(0, i);
728 nPositions[1] = i+__sCmd.find_first_not_of(' ', n+2);
729 g_logger.debug("sSubExpr = " + sSubExpr);
730 _mRight = evalMatOp(sSubExpr, _parser, _data, _functions, _option, _cache);
731 g_logger.debug("_mRight.size() = " + _mRight.printDims());
732 break;
733 }
734 }
735
736 if (_mRight.isEmpty())
737 throw SyntaxError(SyntaxError::NO_MATRIX_FOR_MATOP, sCmd, pos_back+1);
738
739 // Left handed matrix expression
740 int nBraces = 0;
741 p = __sCmd.find_last_not_of(" *", n);
742
743 for (int i = p; i >= 0; i--)
744 {
745 if (__sCmd[i] == ')' || __sCmd[i] == '}' || __sCmd[i] == ']')
746 nBraces++;
747
748 if (__sCmd[i] == '(' || __sCmd[i] == '{' || __sCmd[i] == '[')
749 nBraces--;
750
751 if (!nBraces
752 && (!i || (!isalnum(__sCmd[i-1]) && __sCmd[i-1] != '_' && __sCmd[i-1] != '~')))
753 {
754 std::string sSubExpr = __sCmd.substr(i, p - i+1);
755 nPositions[0] = i;
756 g_logger.debug("sSubExpr = " + sSubExpr);
757 _mLeft = evalMatOp(sSubExpr, _parser, _data, _functions, _option, _cache);
758 g_logger.debug("_mLeft.size() = " + _mLeft.printDims());
759 break;
760 }
761 }
762
763 if (_mLeft.isEmpty())
764 throw SyntaxError(SyntaxError::NO_MATRIX_FOR_MATOP, sCmd, pos_back+1);
765
766 // Perform the actual matrix multiplication
767 _cache.vReturnedMatrices.push_back(multiplyMatrices(_mLeft, _mRight, sCmd, "", pos_back+1));
768
769 // Replace the current multiplication with its return value
770 __sCmd.replace(nPositions[0], nPositions[1]-nPositions[0],
771 "_~returnedMatrix[" + toString((int)_cache.vReturnedMatrices.size()-1)+"]");
772 n = nPositions[0];
773 }
774 }
775 }
776
777 sCmd = __sCmd;
778
779 std::map<size_t, std::string> mDataMatrices;
780 std::map<size_t, std::string> mReturnedMatrices;
781 size_t nColCount = 1; // Minimal size of a matrix
782 size_t nRowCount = 1; // Minimal size of a matrix
783
784 // We need the maximal number of columns for the regular
785 // evaluation of the expression
786 //
787 // Examine the memory accesses, which are still available
788 // in the expression
789 for (unsigned int i = 0; i < _cache.vDataAccesses.size(); i++)
790 {
791 std::string sMatrixName = "_~matrix["+toString((int)i)+"]";
792
793 if (sCmd.find(sMatrixName) == string::npos)
794 continue;
795
796 mDataMatrices[i] = sMatrixName;
797
798 // Get the column count from the dimensions of the indices
799 nRowCount = std::max(nRowCount, _cache.vDataAccesses[i].idx.row.size());
800 nColCount = std::max(nColCount, _cache.vDataAccesses[i].idx.col.size());
801 }
802
803 // Examine now the return values available in the expression
804 for (unsigned int i = 0; i < _cache.vReturnedMatrices.size(); i++)
805 {
806 std::string sMatrixName = "_~returnedMatrix["+toString((int)i)+"]";
807
808 if (sCmd.find(sMatrixName) == string::npos)
809 continue;
810
811 mReturnedMatrices[i] = sMatrixName;
812 nRowCount = std::max(nRowCount, _cache.vReturnedMatrices[i].rows());
813 nColCount = std::max(nColCount, _cache.vReturnedMatrices[i].cols());
814 }
815
816 // Shortcut => only a single matrix
817 if (mDataMatrices.size() == 1 && isEqualStripped(sCmd, mDataMatrices.begin()->second))
818 {
819 auto iter = mDataMatrices.begin();
820 return _data.getTable(_cache.vDataAccesses[iter->first].sName)->readMemAsMatrix(_cache.vDataAccesses[iter->first].idx.row,
821 _cache.vDataAccesses[iter->first].idx.col);
822 }
823
824 if (mReturnedMatrices.size() == 1 && isEqualStripped(sCmd, mReturnedMatrices.begin()->second))
825 return _cache.vReturnedMatrices[mReturnedMatrices.begin()->first];
826
827 // Read now the first column of every matrix in the expression
828 // as vector for the parser
829 //
830 // start with the memory accesses
831 for (const auto& iter : mDataMatrices)
832 {
833 // Get the values using the incdices
834 const MatOpCache::MatOpDataAccess& _access = _cache.vDataAccesses[iter.first];
835 Matrix mat(_data.getTable(_access.sName)->readMemAsMatrix(_access.idx.row, _access.idx.col));
836
837 // Extend this matrix to have enough elements
838 mat.extend(nRowCount, nColCount);
839
840 // Declare the corresponding vector variable
841 _parser.SetVectorVar(iter.second, mat.data());
842 }
843
844 // Get now the first columns of the returned values
845 for (const auto& iter : mReturnedMatrices)
846 {
847 // Extend every matrix to have enough elements
848 _cache.vReturnedMatrices[iter.first].extend(nRowCount, nColCount);
849
850 // Declare the corresponding vector variable
851 _parser.SetVectorVar(iter.second, _cache.vReturnedMatrices[iter.first].data());
852 }
853
854 // Set the expression in the parser
855 _parser.SetExpr(sCmd);
856
857 g_logger.debug("Matrix calculation");
858
859 // Evaluate the first columns
860 v = _parser.Eval(nResults);
861
862 // Create and return a matrix from the calculated
863 // results
864 return Matrix((nResults > 1 && nRowCount == 1 && nColCount == 1) ? nResults : nRowCount, // special case for multiple return values
865 nColCount,
866 v, nResults);
867}
868
869
880static size_t getPrevMatMultiOp(const string& sCmd, size_t nLastPos)
881{
882 int nQuotes = 0;
883
884 for (int i = nLastPos; i >= 0; i--)
885 {
886 if (sCmd[i] == '(' || sCmd[i] == '{')
887 nQuotes++;
888
889 if (sCmd[i] == ')' || sCmd[i] == '}')
890 nQuotes--;
891
892 if (!(nQuotes%2) && sCmd.substr(i,2) == "**")
893 return i;
894 }
895
896 return 0;
897}
898
899
912static Matrix multiplyMatrices(const Matrix& _mLeft, const Matrix& _mRight, const string& sCmd, const string& sExpr, size_t position)
913{
914 if (_mLeft.isEmpty() || _mRight.isEmpty())
916
917 if (_mRight.rows() != _mLeft.cols())
919 _mLeft.printDims() +" vs. "+ _mRight.printDims());
920
921 return _mLeft * _mRight;
922}
923
924
935{
937}
938
939
951Matrix createZeroesMatrix(unsigned int nLines, unsigned int nCols)
952{
953 if (!nLines || !nCols)
955
956 return createFilledMatrix(nLines, nCols, 0.0);
957}
958
959
973static Matrix createMatFromCols(string& sCmd, Parser& _parser, MemoryManager& _data, FunctionDefinitionManager& _functions, const Settings& _option)
974{
975 return transposeMatrix(createMatFromLines(sCmd, _parser, _data, _functions, _option));
976}
977
978
992static Matrix createMatFromColsFilled(string& sCmd, Parser& _parser, MemoryManager& _data, FunctionDefinitionManager& _functions, const Settings& _option)
993{
994 return transposeMatrix(createMatFromLinesFilled(sCmd, _parser, _data, _functions, _option));
995}
996
997
1011static Matrix createMatFromLines(string& sCmd, Parser& _parser, MemoryManager& _data, FunctionDefinitionManager& _functions, const Settings& _option)
1012{
1013 std::vector<std::vector<mu::value_type>> _matfl;
1014 value_type* v = 0;
1015 int nResults = 0;
1016 unsigned int nLineLength = 0;
1017 vector<mu::value_type> vLine;
1018 if (!sCmd.length())
1019 {
1020 _matfl.push_back(vector<mu::value_type>(1,NAN));
1021 }
1022 if (!_functions.call(sCmd))
1024 if (_data.containsTablesOrClusters(sCmd))
1025 {
1026 getDataElements(sCmd, _parser, _data, _option);
1027 }
1028 while (sCmd.length())
1029 {
1030 if (!getNextArgument(sCmd, false).length())
1031 break;
1032 _parser.SetExpr(getNextArgument(sCmd, true));
1033 v = _parser.Eval(nResults);
1034 if ((unsigned)nResults > nLineLength)
1035 nLineLength = (unsigned)nResults;
1036 for (int n = 0; n < nResults; n++)
1037 vLine.push_back(v[n]);
1038 _matfl.push_back(vLine);
1039 vLine.clear();
1040 }
1041 if (!_matfl.size())
1042 {
1043 _matfl.push_back(vector<mu::value_type>(1,NAN));
1044 }
1045
1046 // Groesse ggf. korrigieren
1047
1048 for (unsigned int i = 0; i < _matfl.size(); i++)
1049 {
1050 _matfl[i].resize(nLineLength, 0.0);
1051 }
1052
1053 return Matrix(_matfl);
1054}
1055
1056
1070static Matrix createMatFromLinesFilled(string& sCmd, Parser& _parser, MemoryManager& _data, FunctionDefinitionManager& _functions, const Settings& _option)
1071{
1072 std::vector<std::vector<mu::value_type>> _matfl;
1073 value_type* v = 0;
1074 int nResults = 0;
1075 unsigned int nLineLength = 0;
1076 vector<mu::value_type> vLine;
1077 if (!sCmd.length())
1078 {
1079 _matfl.push_back(vector<mu::value_type>(1,NAN));
1080 }
1081 if (!_functions.call(sCmd))
1083 if (_data.containsTablesOrClusters(sCmd))
1084 {
1085 getDataElements(sCmd, _parser, _data, _option);
1086 }
1087 while (sCmd.length())
1088 {
1089 if (!getNextArgument(sCmd, false).length())
1090 break;
1091 _parser.SetExpr(getNextArgument(sCmd, true));
1092 v = _parser.Eval(nResults);
1093 if ((unsigned)nResults > nLineLength)
1094 nLineLength = (unsigned)nResults;
1095 for (int n = 0; n < nResults; n++)
1096 vLine.push_back(v[n]);
1097 _matfl.push_back(vLine);
1098 vLine.clear();
1099 }
1100 if (!_matfl.size())
1101 {
1102 _matfl.push_back(vector<mu::value_type>(1,NAN));
1103 }
1104
1105 // Groesse entsprechend der Logik korrigieren
1106
1107 for (unsigned int i = 0; i < _matfl.size(); i++)
1108 {
1109 if (_matfl[i].size() == 1)
1110 {
1111 // nur ein Element: wiederholen
1112 _matfl[i].resize(nLineLength, _matfl[i][0]);
1113 }
1114 else
1115 {
1116 vector<mu::value_type> vDeltas = calcDeltasForMatFill(_matfl, i);
1117 while (_matfl[i].size() < nLineLength)
1118 {
1119 _matfl[i].push_back(_matfl[i].back() + vDeltas[(_matfl[i].size()+1) % vDeltas.size()]);
1120 }
1121 }
1122 }
1123
1124 return Matrix(_matfl);
1125}
1126
1127
1140static vector<mu::value_type> calcDeltasForMatFill(const std::vector<std::vector<mu::value_type>>& _mMatrix, unsigned int nLine)
1141{
1142 vector<mu::value_type> vDeltas;
1143 for (unsigned int j = 1; j < _mMatrix[nLine].size(); j++)
1144 {
1145 vDeltas.push_back(_mMatrix[nLine][j]-_mMatrix[nLine][j-1]);
1146 }
1147 return vDeltas;
1148}
1149
1150
1165static Matrix getMatrixElements(string& sExpr, const Matrix& _mMatrix, Parser& _parser, MemoryManager& _data, FunctionDefinitionManager& _functions, const Settings& _option)
1166{
1167 Matrix _mReturn;
1168 Indices _idx = getIndices(sExpr, _mMatrix, _parser, _data, _option);
1169
1170 if (_idx.row.isOpenEnd())
1171 _idx.row.setRange(0, _mMatrix.rows()-1);
1172
1173 if (_idx.col.isOpenEnd())
1174 _idx.col.setRange(0, _mMatrix.cols()-1);
1175
1176 _mReturn = createZeroesMatrix(_idx.row.size(), _idx.col.size());
1177
1178 for (unsigned int i = 0; i < _idx.row.size(); i++)
1179 {
1180 for (unsigned int j = 0; j < _idx.col.size(); j++)
1181 {
1182 if (_idx.row[i] >= (int)_mMatrix.rows() || _idx.col[j] >= (int)_mMatrix.cols())
1184 _idx.row.to_string() + ", " + _idx.col.to_string());
1185
1186 _mReturn(i, j) = _mMatrix(_idx.row[i], _idx.col[j]);
1187 }
1188 }
1189
1190 return _mReturn;
1191}
1192
1193
1194static std::string formatMatrixRow(const Matrix& _mResult, const Settings& _option, size_t row)
1195{
1196 const size_t FIELDLENGTH = 21;
1197 const size_t FIELDLENGTH_W_FILLER = 23;
1198 const size_t PRECISION = 7;
1199
1200 std::string sRow;
1201
1202 for (unsigned int col = 0; col < _mResult.cols(); col++)
1203 {
1204 if (_mResult.cols() > (_option.getWindow()-2-15) / FIELDLENGTH_W_FILLER
1205 && (_option.getWindow()-2-15) / FIELDLENGTH_W_FILLER / 2 == col)
1206 {
1207 sRow += strfill("..., ", FIELDLENGTH_W_FILLER);
1208 col = _mResult.cols() - (_option.getWindow()-2-15) / FIELDLENGTH_W_FILLER / 2 - 1;
1209 continue;
1210 }
1211
1212 sRow += strfill(toString(_mResult(row, col), PRECISION), FIELDLENGTH);
1213
1214 if (col+1 < _mResult.cols())
1215 sRow += ", ";
1216 }
1217
1218 return sRow;
1219}
1220
1221
1231static void showMatrixResult(const Matrix& _mResult, const Settings& _option)
1232{
1234 return;
1235
1236 const size_t FIELDLENGTH = 21;
1237 const size_t FIELDLENGTH_W_FILLER = 23;
1238
1240
1241 if (_mResult.rows() > 10)
1242 {
1243 for (unsigned int i = 0; i < _mResult.rows(); i++)
1244 {
1245 if (!i)
1247 else if (i+1 == _mResult.rows())
1249 else if (i == 5)
1251 else
1253
1254 if (i == 5)
1255 {
1256 for (unsigned int j = 0; j < _mResult.cols(); j++)
1257 {
1258 if (_mResult.cols() > (_option.getWindow()-2-15) / FIELDLENGTH_W_FILLER
1259 && (_option.getWindow()-2-15) / FIELDLENGTH_W_FILLER / 2 == j)
1260 {
1261 NumeReKernel::printPreFmt(strfill("..., ", FIELDLENGTH_W_FILLER));
1262 j = _mResult.cols() - (_option.getWindow()-2-15) / FIELDLENGTH_W_FILLER / 2 - 1;
1263 continue;
1264 }
1265
1266 NumeReKernel::printPreFmt(strfill("...", FIELDLENGTH));
1267
1268 if (j+1 < _mResult.cols())
1270 }
1271
1272 i = _mResult.rows()-6;
1273 }
1274 else
1275 NumeReKernel::printPreFmt(formatMatrixRow(_mResult, _option, i));
1276
1277 if (!i)
1279 else if (i+1 == _mResult.rows())
1281 else
1283 }
1284 }
1285 else if (_mResult.rows() == 1)
1286 {
1287 if (_mResult.cols() == 1)
1288 NumeReKernel::print("(" + toString(_mResult(0), _option.getPrecision()) + ")");
1289 else
1290 NumeReKernel::print("(" + formatMatrixRow(_mResult, _option, 0) + " )");
1291 }
1292 else
1293 {
1294 for (unsigned int i = 0; i < _mResult.rows(); i++)
1295 {
1296 if (!i && _mResult.rows() == 2)
1298 else if (!i)
1300 else if (i+1 == _mResult.rows())
1302 else if (i == (_mResult.rows()-1)/2)
1304 else
1306
1307 NumeReKernel::printPreFmt(formatMatrixRow(_mResult, _option, i));
1308
1309 if (!i)
1311 else if (i+1 == _mResult.rows())
1313 else
1315 }
1316 }
1317
1320 return;
1321}
1322
1323
1337Indices getIndices(const string& sCmd, const Matrix& _mMatrix, Parser& _parser, MemoryManager& _data, const Settings& _option)
1338{
1339 Indices _idx;
1340 string sI[2] = {"<<NONE>>", "<<NONE>>"};
1341 string sJ[2] = {"<<NONE>>", "<<NONE>>"};
1342 string sArgument = "";
1343 unsigned int nPos = 0;
1344 int nParenthesis = 0;
1345 value_type* v = 0;
1346 int nResults = 0;
1347
1348 if (sCmd.find('(') == string::npos)
1349 return _idx;
1350
1351 nPos = sCmd.find('(');
1352
1353 for (unsigned int n = nPos; n < sCmd.length(); n++)
1354 {
1355 if (sCmd[n] == '(')
1356 nParenthesis++;
1357
1358 if (sCmd[n] == ')')
1359 nParenthesis--;
1360
1361 if (!nParenthesis)
1362 {
1363 sArgument = sCmd.substr(nPos+1, n-nPos-1);
1364 break;
1365 }
1366 }
1367
1368 StripSpaces(sArgument);
1369
1370 if (_data.containsTablesOrClusters(sArgument))
1371 getDataElements(sArgument, _parser, _data, _option);
1372
1373 // --> Kurzschreibweise!
1374 if (!sArgument.length())
1375 {
1376 _idx.row = VectorIndex(0LL, _mMatrix.rows());
1377 _idx.col = VectorIndex(0LL, _mMatrix.cols());
1378 return _idx;
1379 }
1380
1381 if (sArgument.find(',') != string::npos)
1382 {
1383 nParenthesis = 0;
1384 nPos = 0;
1385
1386 for (unsigned int n = 0; n < sArgument.length(); n++)
1387 {
1388 if (sArgument[n] == '(' || sArgument[n] == '{')
1389 nParenthesis++;
1390
1391 if (sArgument[n] == ')' || sArgument[n] == '}')
1392 nParenthesis--;
1393
1394 if (sArgument[n] == ':' && !nParenthesis)
1395 {
1396 if (!nPos)
1397 {
1398 if (!n)
1399 sI[0] = "<<EMPTY>>";
1400 else
1401 sI[0] = sArgument.substr(0, n);
1402 }
1403 else if (n == nPos)
1404 {
1405 sJ[0] = "<<EMPTY>>";
1406 }
1407 else
1408 {
1409 sJ[0] = sArgument.substr(nPos, n-nPos);
1410 }
1411
1412 nPos = n+1;
1413 }
1414
1415 if (sArgument[n] == ',' && !nParenthesis)
1416 {
1417 if (!nPos)
1418 {
1419 if (!n)
1420 sI[0] = "<<EMPTY>>";
1421 else
1422 sI[0] = sArgument.substr(0, n);
1423 }
1424 else
1425 {
1426 if (n == nPos)
1427 sI[1] = "<<EMPTY>>";
1428 else
1429 sI[1] = sArgument.substr(nPos, n - nPos);
1430 }
1431
1432 nPos = n+1;
1433 }
1434 }
1435
1436 if (sJ[0] == "<<NONE>>")
1437 {
1438 if (nPos < sArgument.length())
1439 sJ[0] = sArgument.substr(nPos);
1440 else
1441 sJ[0] = "<<EMPTY>>";
1442 }
1443 else if (nPos < sArgument.length())
1444 sJ[1] = sArgument.substr(nPos);
1445 else
1446 sJ[1] = "<<EMPTY>>";
1447
1448 // --> Vektor prüfen <--
1449 if (sI[0] != "<<NONE>>" && sI[1] == "<<NONE>>")
1450 {
1451 _parser.SetExpr(sI[0]);
1452 v = _parser.Eval(nResults);
1453
1454 if (nResults > 1)
1455 {
1456 _idx.row = VectorIndex(v, nResults, 0);
1457 }
1458 else
1459 _idx.row.front() = intCast(v[0])-1;
1460 }
1461
1462 if (sJ[0] != "<<NONE>>" && sJ[1] == "<<NONE>>")
1463 {
1464 _parser.SetExpr(sJ[0]);
1465 v = _parser.Eval(nResults);
1466
1467 if (nResults > 1)
1468 {
1469 _idx.col = VectorIndex(v, nResults, 0);
1470 }
1471 else
1472 _idx.col.front() = intCast(v[0])-1;
1473 }
1474
1475 for (int n = 0; n < 2; n++)
1476 {
1477 if (sI[n] == "<<EMPTY>>")
1478 {
1479 if (n)
1480 _idx.row.back() = _mMatrix.rows()-1;
1481 else
1482 _idx.row.front() = 0;
1483 }
1484 else if (sI[n] != "<<NONE>>")
1485 {
1486 _parser.SetExpr(sI[n]);
1487 _idx.row.setIndex(n, intCast(_parser.Eval())-1);
1488
1489 if (isnan(_parser.Eval().real()) || isinf(_parser.Eval().real()) || _parser.Eval().real() <= 0)
1491 }
1492
1493 if (sJ[n] == "<<EMPTY>>")
1494 {
1495 if (n)
1496 _idx.col.back() = _mMatrix.cols()-1;
1497 else
1498 _idx.col.front() = 0;
1499 }
1500 else if (sJ[n] != "<<NONE>>")
1501 {
1502 _parser.SetExpr(sJ[n]);
1503 _idx.col.setIndex(n, intCast(_parser.Eval())-1);
1504
1505 if (isnan(_parser.Eval().real()) || isinf(_parser.Eval().real()) || _parser.Eval().real() <= 0)
1507 }
1508 }
1509 }
1510
1511 return _idx;
1512}
1513
1514
1524void showMatrix(const vector<vector<mu::value_type> >& _mMatrix)
1525{
1526 showMatrixResult(Matrix(_mMatrix), NumeReKernel::getInstance()->getSettings());
1527}
1528
1540static void parser_declareMatrixReturnValuesForIndices(const string& _sCmd, const vector<Matrix>& vReturnedMatrices, Parser& _parser)
1541{
1542 for (unsigned int j = 0; j < vReturnedMatrices.size(); j++)
1543 {
1544 vector<mu::value_type> v;
1545 if (vReturnedMatrices[j].isScalar())
1546 {
1547 v.push_back(vReturnedMatrices[j](0));
1548 }
1549 else if (vReturnedMatrices[j].rows() == 1
1550 || vReturnedMatrices[j].cols() == 1)
1551 {
1552 v = vReturnedMatrices[j].data();
1553 }
1554 else
1555 {
1556 for (size_t i = 0; i < vReturnedMatrices[j].rows(); i++)
1557 v.push_back(vReturnedMatrices[j](i));
1558 }
1559
1560 // Declare the corresponding vector variable
1561 if (_sCmd.find("_~returnedMatrix["+toString((int)j)+"]") != string::npos)
1562 _parser.SetVectorVar("_~returnedMatrix["+toString((int)j)+"]", v);
1563 }
1564}
1565
1566
1580static void parser_declareDataMatrixValuesForIndices(string& _sCmd, const MatOpCache& _cache, Parser&_parser, MemoryManager& _data)
1581{
1582 for (unsigned int j = 0; j < _cache.vDataAccesses.size(); j++)
1583 {
1584 vector<mu::value_type> v;
1585 const MatOpCache::MatOpDataAccess& _access = _cache.vDataAccesses[j];
1586
1587 // Get the values using the indices
1588 if (_access.idx.row.size() > _access.idx.col.size())
1589 v = _data.getElement(_access.idx.row, VectorIndex(_access.idx.col[0]), _access.sName);
1590 else
1591 v = _data.getElement(VectorIndex(_access.idx.row[0]), _access.idx.col, _access.sName);
1592
1593 // Declare the corresponding vector variable
1594 if (_sCmd.find("_~matrix["+toString((int)j)+"]") != string::npos)
1595 _parser.SetVectorVar("_~matrix["+toString((int)j)+"]", v);
1596 }
1597}
1598
1599
1614static Indices getIndicesForMatrix(const string& sCmd, const MatOpCache& _cache, Parser& _parser, MemoryManager& _data, const Settings& _option)
1615{
1616 string _sCmd = sCmd;
1617
1618 // Declare the return values of the former matrix calculations
1619 // to the parser by extracting the values and creating a vector
1620 // variable
1622
1623 // Declare the already parsed data object matrices in the
1624 // current expressions by parsing their indices, extracting
1625 // the corresponding values and creating a vector variable
1626 parser_declareDataMatrixValuesForIndices(_sCmd, _cache, _parser, _data);
1627
1628 // Return the calculated indices
1629 return getIndices(_sCmd, _parser, _data, _option);
1630}
1631
1632
1643static bool containsMatrices(const string& sExpr, MemoryManager& _data)
1644{
1645 if (_data.containsTablesOrClusters(sExpr) || sExpr.find('{') != string::npos)
1646 return true;
1647
1648 static map<string, MatFuncDef> mMatrixFunctionsMap = getMatrixFunctions();
1649
1650 // search for any matrix function
1651 for (auto iter = mMatrixFunctionsMap.begin(); iter != mMatrixFunctionsMap.end(); ++iter)
1652 {
1653 if (!iter->second.isPureMatFunc)
1654 continue;
1655
1656 size_t match = sExpr.find(iter->first+"(");
1657
1658 if (match != string::npos && (!match || (!isalpha(sExpr[match-1]) && sExpr[match-1] != '_')))
1659 return true;
1660 }
1661
1662 return false;
1663}
1664
void checkAssertion(mu::value_type *v, int nNum)
Checks the return value of a muParser evaluated result.
Definition: error.cpp:244
void debug(const std::string &sMessage)
Convenience member function.
Definition: logger.hpp:94
This class implements the function definition managing instance.
Definition: define.hpp:74
bool call(std::string &sExpr, int nRecursion=0)
This function searches for known custom definitions in the passed expression and replaces them with t...
Definition: define.cpp:801
This class defines a dynamic size 2D matrix with a single 1D internal buffer. If the internal buffer ...
std::string printDims() const
Convert the dimensions to a printable string.
void extend(size_t r, size_t c)
Extend this matrix to be prepared for the acutal mathematical operation. Scalars are not touched and ...
std::vector< mu::value_type > & data()
Get a reference to the internal data structure.
bool isEmpty() const
Simple function to identify empty matrices.
size_t cols() const
The cols of this matrix.
size_t rows() const
The rows of this matrix.
This class represents a single table in memory, or a - so to say - single memory page to be handled b...
Definition: memory.hpp:68
void markModified()
Mark this table as modified.
Definition: memory.cpp:1121
void writeData(int _nLine, int _nCol, const mu::value_type &_dData)
This member function writes the passed value to the selected position. The table is automatically enl...
Definition: memory.cpp:1219
void writeDataDirectUnsafe(int _nLine, int _nCol, const mu::value_type &_dData)
This member function provides an even more unsafe but direct way of writing data to the table....
Definition: memory.cpp:1271
Matrix readMemAsMatrix(const VectorIndex &_vLine, const VectorIndex &_vCol) const
This member function returns the elements stored at the selected positions as a Matrix.
Definition: memory.cpp:497
This class represents the central memory managing instance. It will handle all tables and clusters,...
mu::value_type getElement(int _nLine, int _nCol, const std::string &_sTable) const
void deleteBulk(const std::string &_sCache, int i1, int i2, int j1=0, int j2=0)
int getLines(StringView sTable, bool _bFull=false) const
const std::map< std::string, std::pair< size_t, size_t > > & getTableMap() const
bool isTable(const std::string &sTable) const
This member function returns, whether the passed table name corresponds to a known table.
bool addTable(const std::string &sCache, const Settings &_option)
This member function creates a new table. It is checked, whether its name is valid and not already us...
bool resizeTable(int _nCols, const std::string &_sTable)
Memory * getTable(const std::string &sTable)
This member function returns a pointer to an existing Memory instance representing the selected table...
bool containsTablesOrClusters(const std::string &sCmdLine)
This member function evaluates, whether the passed command line contains tables or clusters.
int getCols(StringView sTable, bool _bFull=false) const
This class represents a whole cluster. The single items are stored as pointers to the abstract cluste...
Definition: cluster.hpp:325
void clear()
This member function clears the internal memory buffer and frees the associated memory.
Definition: cluster.cpp:395
void setDouble(size_t i, const mu::value_type &value)
This member function assigns a value as data for the i-th cluster item in memory. The type of the i-t...
Definition: cluster.cpp:561
Cluster & getCluster(StringView sCluster)
This member function returns a reference to the cluster indicated by the passed cluster identifier.
Definition: cluster.cpp:2077
Cluster & newCluster(const std::string &sCluster)
This member function creates a new cluster from the passed cluster identifier and returns a reference...
Definition: cluster.cpp:2139
bool isCluster(StringView sCluster) const
This member function returns true, if the passed cluster identifier can be found in the internal map.
Definition: cluster.cpp:2041
const std::map< std::string, Cluster > & getClusterMap() const
Definition: cluster.hpp:475
static NumeReKernel * getInstance()
This static member function returns a a pointer to the singleton instance of the kernel.
Definition: kernel.hpp:221
static bool bSupressAnswer
Definition: kernel.hpp:199
static void printPreFmt(const std::string &__sLine, bool printingEnabled=true)
This member function appends the pre- formatted string to the buffer and informs the terminal that we...
Definition: kernel.cpp:2683
static void print(const std::string &__sLine, bool printingEnabled=true)
This member function appends the passed string as a new output line to the buffer and informs the ter...
Definition: kernel.cpp:2636
static void flush()
Inform the terminal to write the current output buffer as soon as possible.
Definition: kernel.cpp:3684
static void toggleTableStatus()
Toggles the table writing status, which will reduce the number or events send to the terminal.
Definition: kernel.cpp:3671
This class manages the setting values of the internal (kernel) settings of this application.
Definition: settings.hpp:663
bool systemPrints() const
Returns, whether system messages shall be printed to the terminal.
Definition: settings.hpp:1140
size_t getPrecision() const
Returns the precision for displaying floating numbers in the terminal. This value determines the numb...
Definition: settings.hpp:1000
size_t getWindow(int nWindow=0) const
Returns the current window size of the terminal.
Definition: settings.hpp:1101
This class is the immutable (const) version of a string view. It can be constructed from a MutableStr...
Common exception class for all exceptions thrown in NumeRe.
Definition: error.hpp:32
@ INVALID_DATA_ACCESS
Definition: error.hpp:125
@ NO_MATRIX_FOR_MATOP
Definition: error.hpp:175
@ MATRIX_CANNOT_HAVE_ZERO_SIZE
Definition: error.hpp:155
@ FUNCTION_ERROR
Definition: error.hpp:110
@ WRONG_MATRIX_DIMENSIONS_FOR_MATOP
Definition: error.hpp:227
@ INVALID_INDEX
Definition: error.hpp:129
static size_t invalid_position
Definition: error.hpp:235
This class abstracts all the index logics, i.e. the logical differences between single indices and in...
Definition: structures.hpp:42
VectorIndex subidx(size_t pos, size_t nLen=std::string::npos) const
This member function returns a subset of the internal stored index just like the std::string::substr(...
Definition: structures.hpp:238
int max() const
This function calculates the maximal index value obtained from the values stored internally.
Definition: structures.hpp:558
size_t size() const
This member function returns the size of the indices stored in this class.
Definition: structures.hpp:314
bool isOpenEnd() const
This member function determines, whether the internal index set has an open end.
Definition: structures.hpp:614
void setRange(int nMin, int nMax)
This member function can be used to force the indices stored internally to be in a defined interval....
Definition: structures.hpp:712
std::string to_string() const
This member function converts the vector indexes contents into a human-readable string representation...
Definition: structures.hpp:770
void setIndex(size_t nthIndex, int nVal)
This member function can be used to set the index at a special position. This will expand the interna...
Definition: structures.hpp:394
int & back()
This member function returns a reference to the final index value stored internally.
Definition: structures.hpp:653
int & front()
This member function returns a reference to the first index value stored internally.
Definition: structures.hpp:640
void SetExpr(StringView a_sExpr)
Set the expression. Triggers first time calculation thus the creation of the bytecode and scanning of...
value_type Eval()
Single-value wrapper around the vectorized overload of this member function.
void SetVectorVar(const std::string &sVarName, const std::vector< mu::value_type > &vVar, bool bAddVectorType=false)
This member function copies the passed vector into the internal storage referencing it with the passe...
Mathematical expressions parser.
Definition: muParser.h:51
string getDataElements(string &sLine, Parser &_parser, MemoryManager &_data, const Settings &_option, int options)
Searches the passed string for calls to any table or cluster and replaces them with internal vectors ...
Definition: dataaccess.cpp:276
bool isValidIndexSet(const Indices &_idx)
Definition: dataaccess.hpp:81
Assertion _assertionHandler
Definition: error.cpp:27
std::string strfill(const std::string &sString, unsigned int nWidth, char cFill=' ', bool limit=false)
This function fills the passed string up to the width nWidth with the characters cFill....
Definition: kernel.hpp:408
DetachedLogger g_logger
Definition: logger.cpp:23
@ MATSIG_MAT_F
@ MATSIG_MAT
@ MATSIG_MAT_F_N
@ MATSIG_N_MOPT
@ MATSIG_MAT_MAT_MAT
@ MATSIG_MAT_MAT
@ MATSIG_MAT_MAT_N
@ MATSIG_MAT_N_MOPT
@ MATSIG_MAT_NOPT
@ MATSIG_INVALID
static std::map< std::string, MatFuncDef > getMatrixFunctions()
Returns a map containing all declared and "standard" matrix functions.
Definition: matfuncs.hpp:3438
int const MatFuncErrorInfo & errorInfo
Definition: matfuncs.hpp:358
static Matrix createFilledMatrix(size_t n, size_t m, const mu::value_type &val)
This static function returns a matrix filled with the passed value of the defined size.
Definition: matfuncs.hpp:64
static void parser_declareDataMatrixValuesForIndices(string &_sCmd, const MatOpCache &_cache, Parser &_parser, MemoryManager &_data)
Static helper function for parser_getIndicesForMatrix(), which will handle the indices of already par...
static Indices getIndicesForMatrix(const string &sCmd, const MatOpCache &_cache, Parser &_parser, MemoryManager &_data, const Settings &_option)
Static wrapper function for resolving already parsed datafile matrix elements and evaluated matrix ex...
static void showMatrixResult(const Matrix &_mResult, const Settings &_option)
This static function formats and prints the calculated matrix to the terminal.
static Matrix getMatrixElements(string &sExpr, const Matrix &_mMatrix, Parser &_parser, MemoryManager &_data, FunctionDefinitionManager &_functions, const Settings &_option)
This static function extracts parts of the passed matrix based upon the passed index equations.
Matrix transposeMatrix(const Matrix &_mMatrix)
This static function will transpose the passed matrix (exchange rows with columns).
bool performMatrixOperation(string &sCmd, Parser &_parser, MemoryManager &_data, FunctionDefinitionManager &_functions, const Settings &_option)
This function is the main interface to the matrix operations.
static void parser_declareMatrixReturnValuesForIndices(const string &_sCmd, const vector< Matrix > &vReturnedMatrices, Parser &_parser)
Static helper function for parser_getIndicesForMatrix(), which will handle the return values of matri...
Indices getIndices(const string &sCmd, const Matrix &_mMatrix, Parser &_parser, MemoryManager &_data, const Settings &_option)
This function creates an Indices object, which is filled with the indices specified by the index equa...
static std::string formatMatrixRow(const Matrix &_mResult, const Settings &_option, size_t row)
Matrix createZeroesMatrix(unsigned int nLines, unsigned int nCols)
This function returns a matrix filled with zeros with the defined lines and columns.
static Matrix createMatFromColsFilled(string &sCmd, Parser &_parser, MemoryManager &_data, FunctionDefinitionManager &_functions, const Settings &_option)
This static function creates a matrix from the passed columns.
static bool containsMatrices(const string &sExpr, MemoryManager &_data)
This static function evaluates, whether there are matrix expressions in the passed expression.
static Matrix createMatFromLines(string &sCmd, Parser &_parser, MemoryManager &_data, FunctionDefinitionManager &_functions, const Settings &_option)
This static function creates a matrix from the passed lines.
static Matrix createMatFromLinesFilled(string &sCmd, Parser &_parser, MemoryManager &_data, FunctionDefinitionManager &_functions, const Settings &_option)
This static function creates a matrix from the passed lines.
static Matrix multiplyMatrices(const Matrix &_mLeft, const Matrix &_mRight, const string &sCmd, const string &sExpr, size_t position)
This static function performs the multiplication of two matrices.
void showMatrix(const vector< vector< mu::value_type > > &_mMatrix)
Simple wrapper for the function parser_ShowMatrixResult() to be accessible from the outside.
static Matrix createMatFromCols(string &sCmd, Parser &_parser, MemoryManager &_data, FunctionDefinitionManager &_functions, const Settings &_option)
This static function creates a matrix from the passed columns.
static Matrix evalMatOp(string &sCmd, Parser &_parser, MemoryManager &_data, FunctionDefinitionManager &_functions, const Settings &_option, MatOpCache &_cache)
This is the actual worker function for matrix operations. It will be called recursively for functions...
static vector< mu::value_type > calcDeltasForMatFill(const std::vector< std::vector< mu::value_type > > &_mMatrix, unsigned int nLine)
This static function is used to calculate the differences between consecutive matrix elements.
static size_t getPrevMatMultiOp(const string &sCmd, size_t nLastPos)
This static function will search for the position of the next (left-hand) matrix multiplication opera...
unsigned int getMatchingParenthesis(const StringView &)
Returns the position of the closing parenthesis.
Definition: tools.cpp:414
MUP_BASETYPE value_type
The numeric datatype used by the parser.
Definition: muParserDef.h:251
bool isnan(const value_type &v)
Definition: muParserDef.h:379
bool isinf(const value_type &v)
Definition: muParserDef.h:374
string addMissingVectorComponent(const string &sVectorComponent, const string &sLeft, const string &sRight, bool bAddStrings)
This function determines the value of missing vector components (i.e. a vector contains not enough el...
bool evaluateIndices(const string &sCache, Indices &_idx, MemoryManager &_data)
This function will evaluate the passed indices, so that they match the dimensions of the passed cache...
#define max(a, b)
Definition: resampler.cpp:30
void StripSpaces(std::string &)
Removes leading and trailing white spaces and tabulator characters.
int StrToInt(const std::string &)
Converts a string into an integer.
bool isEqualStripped(StringView str1, StringView str2)
Returns true, if the contents of the strings are equal, if all surrounding whitespaces will be stripp...
std::string getNextArgument(std::string &sArgList, bool bCut)
Definition: tools.cpp:2294
This structure is central for managing the indices of a table or cluster read or write data access....
VectorIndex col
VectorIndex row
Defines a Matrix.
Defines the needed information for displaying a reasonable error information.
std::vector< MatOpDataAccess > vDataAccesses
std::vector< Matrix > vReturnedMatrices
long long int intCast(const std::complex< double > &)
Casts the real part of the complex number to an integer and avoids rounding errors.
Definition: tools.cpp:1824
std::string toString(int)
Converts an integer to a string without the Settings bloat.
Match findCommand(StringView sCmd, const std::string &sCommand)
This function is very important for the command handler.
Definition: tools.cpp:1275
void evalRecursiveExpressions(string &sExpr)
This function converts the recursive assignments like VAR += VAL into VAR = VAR + (VAL)
Definition: tools.cpp:3346
bool isDelimiter(char c)
This function determines, if the passed character is a delimiter character.
Definition: tools.cpp:1852