NumeRe v1.1.4
NumeRe: Framework für Numerische Rechnungen
indices.cpp
Go to the documentation of this file.
1/*****************************************************************************
2 NumeRe: Framework fuer Numerische Rechnungen
3 Copyright (C) 2018 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
19#include "dataaccess.hpp"
20#include "../utils/tools.hpp"
21#include "../../kernel.hpp"
22#include <vector>
23
24using namespace std;
25using namespace mu;
26
27static void handleArgumentForIndices(Indices& _idx, Parser& _parser, MemoryManager& _data, StringView sArgument, StringView sCmd);
28static void extractIndexList(StringView sCols, vector<StringView>& vLines, vector<StringView>& vCols);
29static void handleIndexVectors(Parser& _parser, VectorIndex& _vIdx, StringView sIndex);
30static void handleCasualIndices(Parser& _parser, Indices& _idx, vector<StringView>& vLines, vector<StringView>& vCols, StringView sCmd);
31static void handleSingleCasualIndex(VectorIndex& _vIdx, vector<StringView>& vIndex, string& sIndexExpressions, vector<int>& vIndexNumbers, int sign);
32static void expandIndexVectors(Indices& _idx, MemoryManager& _data, StringView sCmd);
33static void expandStringIndexVectors(Indices& _idx, MemoryManager& _data);
34
35
49Indices getIndices(StringView sCmd, Parser& _parser, MemoryManager& _data, const Settings& _option)
50{
51 Indices _idx;
52 getIndices(sCmd, _idx, _parser, _data, _option);
53 return _idx;
54}
55
56
70void getIndices(StringView sCmd, Indices& _idx, Parser& _parser, MemoryManager& _data, const Settings& _option)
71{
72 StringView sTableName;
73 StringView sIndices;
74 size_t nPos = 0;
75
76 // Check, whether indices are available
77 if ((nPos = sCmd.find_first_of("({")) == string::npos)
78 return;
79
80 // Find parenthesis position and get the matching closing parenthesis
81 size_t nClosingParens = getMatchingParenthesis(sCmd.subview(nPos));
82
83 // Return, if the closing parenthesis is missing
84 if (nClosingParens == string::npos)
85 return;
86
87 sTableName = sCmd.subview(0, nPos);
88
89 // Remove leading whitespaces and operators
90 for (size_t i = 0; i < sTableName.length(); i++)
91 {
92 // First character of a table is either
93 // and underscore or an alphabetic character.
94 // Digits are not allowed
95 if (sTableName[i] == '_' || isalpha(sTableName[i]))
96 {
97 if (i)
98 sTableName.trim_front(i);
99
100 break;
101 }
102 }
103
104 sIndices = sCmd.subview(nPos+1, nClosingParens-1);
105
106 // Remove not necessary white spaces
107 sIndices.strip();
108
109 // This is the handler for the abbreviation TABLE() == TABLE(:,:)
110 if (!sIndices.length())
111 {
114 return;
115 }
116 else
117 _idx.sCompiledAccessEquation.assign(sIndices.begin(), sIndices.end());
118
119 // If the argument contains tables, get their values. This leads to a recursion!
121 getDataElements(_idx.sCompiledAccessEquation, _parser, _data, _option);
122
123 // update the dimension variables
124 if (sCmd[nPos] == '(')
125 _data.updateDimensionVariables(sTableName);
126 else
127 _data.updateClusterSizeVariables(sTableName);
128
129 //_idx.row.setIndex(0,0);
130 //_idx.col.setIndex(0,0);
131 //return;
132
133#warning TODO (numere#3#08/15/21): Checking for string variables here is inefficient
134 if (NumeReKernel::getInstance()->getStringParser().containsStringVectorVars(_idx.sCompiledAccessEquation))
135 {
137 g_logger.debug("_idx.sCompiledAccessEquation contains string vector vars " + _idx.sCompiledAccessEquation);
138 _idx.sCompiledAccessEquation.clear();
139
140 for (std::string& index : idc)
141 {
142 if (NumeReKernel::getInstance()->getStringParser().containsStringVectorVars(index))
143 {
144 std::string sDummy;
145 bool isVector = index.front() == '{' && index.back() == '}';
147
148 if (isVector)
149 index = "{" + index + "}";
150 }
151
152 if (_idx.sCompiledAccessEquation.length())
153 _idx.sCompiledAccessEquation += ",";
154
155 _idx.sCompiledAccessEquation += index;
156 }
157
158 }
159
160 // If the argument contains a comma, handle it as a usual index list
161 handleArgumentForIndices(_idx, _parser, _data, _idx.sCompiledAccessEquation, sCmd);
162}
163
164
165/*
166 * LOCAL FUNCTIONS FOR parser_getIndices()
167 */
168
182static void handleArgumentForIndices(Indices& _idx, Parser& _parser, MemoryManager& _data, StringView sArgument, StringView sCmd)
183{
184 vector<StringView> vLines;
185 vector<StringView> vCols;
186
187 // extract the (textual) indices from the argument list and store it in sI and sJ
188 extractIndexList(sArgument, vLines, vCols);
189 //_idx.row.setIndex(0,0);
190 //_idx.col.setIndex(0,0);
191 //return;
192
193 // Detect, whether the line indices are candidates
194 // for vectors
195 if (vLines.size() == 1)
196 {
197 // Try to match the textual indices to vectors
198 handleIndexVectors(_parser, _idx.row, vLines.front());
199 }
200
201 // Detect, whether the column indices are candidates
202 // for vectors
203 if (vCols.size() == 1)
204 {
205 // Try to match the textual indices to vectors
206 handleIndexVectors(_parser, _idx.col, vCols.front());
207 }
208
209 // Ensure that the indices are casuals and no indices
210 if (vLines.size() > 1 || vCols.size() > 1)
211 {
212 // Handle the casual indices
213 handleCasualIndices(_parser, _idx, vLines, vCols, sCmd);
214 }
215
216 if (_idx.row.numberOfNodes() > 2 || _idx.col.numberOfNodes() > 2)
217 {
218 // Expand the casual indices to vectors if needed
219 expandIndexVectors(_idx, _data, sCmd);
220 }
221}
222
223
236static void extractIndexList(StringView sCols, vector<StringView>& vLines, vector<StringView>& vCols)
237{
238 // Split line and column indices at
239 // the comma (if it is available). Otherwise
240 // only the line indices are available
241 StringView sLines(getNextViewedArgument(sCols));
242
243 bool openEnd = sLines.back() == ':';
244
245 // Split the line indices
246 vLines.push_back(getNextViewedIndex(sLines));
247
248 sLines.strip();
249
250 if (sLines.length())
251 vLines.push_back(sLines);
252 else if (openEnd)
253 vLines.push_back(StringView());
254
255 // If the column indices are available,
256 // split them also. Otherwise use an
257 // empty StringView instance. It's possible that the
258 // column indices are more than two.
259 if (sCols.length())
260 {
261 openEnd = sCols.back() == ':';
262
263 vCols.push_back(getNextViewedIndex(sCols));
264
265 // As long as there's a column index
266 // available, separate it here
267 while (sCols.length())
268 {
269 vCols.push_back(getNextViewedIndex(sCols));
270 }
271
272 if (openEnd)
273 vCols.push_back(StringView());
274 }
275 else
276 vCols.push_back(StringView());
277}
278
279
290static void handleIndexVectors(Parser& _parser, VectorIndex& _vIdx, StringView sIndex)
291{
293 int nResults;
294
295 if (!sIndex.length())
296 _vIdx.front() = 0;
297 else if (sIndex == "#")
298 _vIdx.front() = VectorIndex::STRING;
299 else
300 {
301 _parser.SetExpr(sIndex);
302 v = _parser.Eval(nResults);
303
304 if (nResults > 1)
305 {
306 // vector
307 _vIdx = VectorIndex(v, nResults, 0);
308 }
309 else if (!isnan(v[0].real()) && intCast(v[0]) > 0) // single index
310 _vIdx.front() = intCast(v[0]) - 1;
311 }
312}
313
314
329static void handleSingleCasualIndex(VectorIndex& _vIdx, vector<StringView>& vIndex, string& sIndexExpressions, vector<int>& vIndexNumbers, int sign)
330{
331 for (size_t n = 0; n < vIndex.size(); n++)
332 {
333 if (!vIndex[n].length())
334 {
335 if (n)
336 _vIdx.setIndex(n, VectorIndex::OPEN_END); //special one: last possible index
337 else
338 _vIdx.front() = 0;
339 }
340 else
341 {
342 if (_vIdx.front() != VectorIndex::STRING)
343 {
344 // connect the indices
345 if (sIndexExpressions.length())
346 sIndexExpressions += ",";
347
348 sIndexExpressions += vIndex[n].to_string();
349 // Store the assignment (lines are positive)
350 vIndexNumbers.push_back(sign*(n + 1));
351 }
352 }
353 }
354}
355
356
369static std::string convertToString(value_type* v, const vector<int> vIndexNumbers)
370{
371 std::string sIndexExpression;
372
373 for (size_t i = 0; i < vIndexNumbers.size(); i++)
374 {
375 if (i)
376 {
377 if (vIndexNumbers[i-1] > 0 && vIndexNumbers[i] < 0)
378 sIndexExpression += ", ";
379 else
380 sIndexExpression += ':';
381 }
382
383 sIndexExpression += toString(v[i], 5);
384 }
385
386 return sIndexExpression;
387}
388
389
404static void handleCasualIndices(Parser& _parser, Indices& _idx, vector<StringView>& vLines, vector<StringView>& vCols, StringView sCmd)
405{
406 string sIndexExpressions;
407 vector<int> vIndexNumbers;
408
409 // Go through all indices and connect them to one single equation
410 // store the assignment of the indices
411 if (!_idx.row.isValid())
412 handleSingleCasualIndex(_idx.row, vLines, sIndexExpressions, vIndexNumbers, 1);
413
414 // Go through the column indices separately,
415 // because they might be more than two
416 if (!_idx.col.isValid())
417 handleSingleCasualIndex(_idx.col, vCols, sIndexExpressions, vIndexNumbers, -1);
418
419 // If the index expression list has a length, evaluate it
420 if (sIndexExpressions.length())
421 {
422 _parser.SetExpr(sIndexExpressions);
423 int nResults;
424 mu::value_type* v = _parser.Eval(nResults);
425
426 // check whether the number of the results is matching
427 if ((size_t)nResults != vIndexNumbers.size())
429
430 // map the results to their assignments
431 for (int i = 0; i < nResults; i++)
432 {
433 if (isinf(v[i].real())) // infinity => last possible index
434 v[i] = -1; // only -1 because it will be decremented in the following lines
435 else if (isnan(v[i].real()) || intCast(v[i]) <= 0LL)
436 {
437 std::string sToken;
438
439 if (vIndexNumbers.front() > 0 && vIndexNumbers.back() < 0)
440 sToken = convertToString(v, vIndexNumbers);
441 else if (vIndexNumbers.front() > 0)
442 {
443 sToken = convertToString(v, vIndexNumbers);
444 sToken += ", " + _idx.col.to_string();
445 }
446 else
447 {
448 sToken = _idx.row.to_string() + ", ";
449 sToken += convertToString(v, vIndexNumbers);
450 }
451
453 }
454
455 if (vIndexNumbers[i] > 0)
456 _idx.row.setIndex(vIndexNumbers[i] - 1, intCast(v[i]) - 1);
457 else
458 _idx.col.setIndex(abs(vIndexNumbers[i]) - 1, intCast(v[i]) - 1);
459 }
460 }
461}
462
463
475static void expandIndexVectors(Indices& _idx, MemoryManager& _data, StringView sCmd)
476{
477 // Get the cache name from the command string
478 // should now only contain the name of the table
479 StringView sCache = sCmd.subview(0, sCmd.find_first_of("({"));
480 bool isCluster = sCmd[sCache.length()] == '{';
481
482 // remove whitespaces
483 sCache.strip();
484
485 // check, whether it exists
486 if (!sCache.length())
488
489 // Ensure that the indices are valid
490 if (!_idx.row.isValid() || !_idx.col.isValid())
492
493 // Is it the "string" object?
494 if (sCache == "string")
495 {
496 expandStringIndexVectors(_idx, _data);
497 return;
498 }
499
500 // If the cache is not really a cache
501 if (!isCluster && !_data.isTable(sCache.to_string()))
503}
504
505
517{
518 if (_idx.row.isOpenEnd())
519 {
520 _idx.row.setRange(0, _data.getStringElements()-1);
521 }
522
523 if (_idx.col.isOpenEnd())
524 {
525 _idx.col.setRange(0, _data.getStringCols()-1);
526 }
527}
528
void debug(const std::string &sMessage)
Convenience member function.
Definition: logger.hpp:94
This class extends the std::vector for endlessness.
Definition: structures.hpp:838
This class represents the central memory managing instance. It will handle all tables and clusters,...
bool isTable(const std::string &sTable) const
This member function returns, whether the passed table name corresponds to a known table.
bool updateDimensionVariables(StringView sTableName)
This member function updates the dimension variables for the selected table to be used in expressions...
bool containsTablesOrClusters(const std::string &sCmdLine)
This member function evaluates, whether the passed command line contains tables or clusters.
bool updateClusterSizeVariables(StringView sCluster)
This member function updates the dimension variable reserved for cluster accesses with the size of th...
Definition: cluster.cpp:2245
StringParserRetVal evalAndFormat(std::string &sLine, std::string &sCache, bool bSilent=false, bool bCheckAssertions=false)
This public member function evaluates the passed string expression and formats the results for the co...
static NumeReKernel * getInstance()
This static member function returns a a pointer to the singleton instance of the kernel.
Definition: kernel.hpp:221
NumeRe::StringParser & getStringParser()
Definition: kernel.hpp:286
This class manages the setting values of the internal (kernel) settings of this application.
Definition: settings.hpp:663
unsigned int getStringCols() const
unsigned int getStringElements(unsigned int nCol=std::string::npos) const
void strip()
This member function shrinks the viewed section to remove all leading or trailing whitespace characte...
void trim_front(size_t len)
This member function can be used to remove characters from the front of the viewed section.
size_t find_first_of(const std::string &findstr, size_t pos=0) const
Wrapper member function for std::string::find_first_of()
const char & back() const
This member function provides a const char reference to the last character in the viewed section.
std::string to_string() const
This member function returns a copy of the viewed section of the string (via std::string::substr)....
std::string::const_iterator end() const
This member function provides an iterator to the end of the viewed section of the internal string.
size_t length() const
This member function simply returns the length of the viewed section.
std::string::const_iterator begin() const
This member function provides an iterator to the beginning of the viewed section of the internal stri...
This class is the immutable (const) version of a string view. It can be constructed from a MutableStr...
StringView subview(size_t pos=0, size_t len=std::string::npos) const
This member function creates a new StringView class instance using the selected position and length a...
Common exception class for all exceptions thrown in NumeRe.
Definition: error.hpp:32
@ INVALID_DATA_ACCESS
Definition: error.hpp:125
@ 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
bool isValid() const
This member function determines, whether the internal index set is valid.
Definition: structures.hpp:601
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 & front()
This member function returns a reference to the first index value stored internally.
Definition: structures.hpp:640
size_t numberOfNodes() const
This member function returns the number of nodes describing the index set, which is stored internally...
Definition: structures.hpp:340
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.
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
Indices getIndices(StringView sCmd, Parser &_parser, MemoryManager &_data, const Settings &_option)
Wrapper for the new getIndices function interface.
Definition: indices.cpp:49
static void handleArgumentForIndices(Indices &_idx, Parser &_parser, MemoryManager &_data, StringView sArgument, StringView sCmd)
This static function is the main driver function for extracting the indices into VectorIndex represen...
Definition: indices.cpp:182
static void handleSingleCasualIndex(VectorIndex &_vIdx, vector< StringView > &vIndex, string &sIndexExpressions, vector< int > &vIndexNumbers, int sign)
This static function is a helper function for handleCasualIndices(), which will be applied to row and...
Definition: indices.cpp:329
static void handleCasualIndices(Parser &_parser, Indices &_idx, vector< StringView > &vLines, vector< StringView > &vCols, StringView sCmd)
This function will evaluate all indices, which are interpreted as casual indices, at once and store t...
Definition: indices.cpp:404
static void handleIndexVectors(Parser &_parser, VectorIndex &_vIdx, StringView sIndex)
This static function will evaluate the indices and it tries to match it to a vector.
Definition: indices.cpp:290
static void extractIndexList(StringView sCols, vector< StringView > &vLines, vector< StringView > &vCols)
This static function separates the argument into its row and column parts and returns them as vectors...
Definition: indices.cpp:236
static void expandStringIndexVectors(Indices &_idx, MemoryManager &_data)
This static function expands the indices into vectors, if the current object is the string object.
Definition: indices.cpp:516
static std::string convertToString(value_type *v, const vector< int > vIndexNumbers)
This static function is a simple helper to convert the numerical results into a string,...
Definition: indices.cpp:369
static void expandIndexVectors(Indices &_idx, MemoryManager &_data, StringView sCmd)
This function will expand casual indices into vectors. Actually, it is only used for the special case...
Definition: indices.cpp:475
DetachedLogger g_logger
Definition: logger.cpp:23
unsigned int getMatchingParenthesis(const StringView &)
Returns the position of the closing parenthesis.
Definition: tools.cpp:414
CONSTCD11 std::chrono::duration< Rep, Period > abs(std::chrono::duration< Rep, Period > d)
Definition: date.h:1317
Namespace for mathematical applications.
Definition: muParser.cpp:53
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
std::vector< double > real(const std::vector< value_type > &vVec)
bool isinf(const value_type &v)
Definition: muParserDef.h:374
This structure is central for managing the indices of a table or cluster read or write data access....
VectorIndex col
VectorIndex row
std::string sCompiledAccessEquation
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.
StringView getNextViewedIndex(StringView &sView)
Definition: tools.cpp:2332
StringView getNextViewedArgument(StringView &sView)
Definition: tools.cpp:2327
EndlessVector< StringView > getAllArguments(StringView sArgList)
Splits up the complete argument list and returns them as an EndlessVector.
Definition: tools.cpp:2346