MicroModelicaCCompiler  4.5.3
index.cpp
Go to the documentation of this file.
1 /*****************************************************************************
2 
3  This file is part of QSS Solver.
4 
5  QSS Solver 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  QSS Solver 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 QSS Solver. If not, see <http://www.gnu.org/licenses/>.
17 
18  ******************************************************************************/
19 
20 #include "index.hpp"
21 
22 #include <sstream>
23 
24 #include <ir/helpers.hpp>
25 #include <ast/ast_builder.hpp>
26 #include <ast/expression.hpp>
27 #include <ast/equation.hpp>
28 #include <ast/statement.hpp>
29 #include <util/error.hpp>
30 #include <util/model_config.hpp>
31 #include <util/util.hpp>
32 #include <util/visitors/eval_init_exp.hpp>
33 #include <util/visitors/get_index_usage.hpp>
34 #include <util/visitors/is_constant_index.hpp>
35 #include <util/visitors/parse_index.hpp>
36 #include <util/visitors/partial_eval_exp.hpp>
37 #include <util/visitors/replace_index.hpp>
38 #include <util/visitors/revert_index.hpp>
39 
40 namespace MicroModelica {
41 using namespace Deps;
42 using namespace Util;
43 namespace IR {
44 
45 IndexDefinition::IndexDefinition() : _variable(), _constant(0), _factor(1) {}
46 
47 IndexDefinition::IndexDefinition(string variable, int constant, int factor) : _variable(variable), _constant(constant), _factor(factor) {}
48 
49 int IndexDefinition::constant() { return _constant; }
50 
51 int IndexDefinition::factor() { return _factor; }
52 
53 string IndexDefinition::variable() { return _variable; }
54 
55 Index::Index(Expression exp) : _indexes(), _exp(exp) { parseIndexes(); }
56 
58 {
59  // Iterate over the expression indexes and generate IndexDefinition for each one.
60  AST_Expression exp = _exp.expression();
61  assert(exp->expressionType() == EXPCOMPREF);
62  AST_Expression_ComponentReference ref = exp->getAsComponentReference();
63  int dim = 0;
64  if (ref->hasIndexes()) {
65  AST_ExpressionList indexes = ref->firstIndex();
66  AST_ExpressionListIterator it;
67  foreach (it, indexes) {
68  ParseIndex parse_index;
70  PartialEvalExp partial_eval;
71  parse_index.apply(partial_eval.apply(current_element(it)));
72  _indexes[dim++] = IndexDefinition(parse_index.variable(), parse_index.constant(), parse_index.factor());
73  }
74  }
75 }
76 
77 vector<int> Index::initValues(Option<Range> range)
78 {
79  assert(!isEmpty());
80  vector<int> init_values;
81  size_t size = _indexes.size();
82  if (_exp.reference()->isScalar()) {
83  init_values.push_back(0);
84  } else if (isConstant()) {
85  assert(_indexes.size());
86  for (size_t i = 0; i < size; i++) {
87  IndexDefinition idx_def = _indexes[i];
88  init_values.push_back(idx_def.constant());
89  }
90  } else {
91  assert(range);
92  for (size_t i = 0; i < size; i++) {
93  IndexDefinition idx_def = _indexes[i];
94  if (idx_def.variable().empty()) {
95  init_values.push_back(idx_def.constant());
96  } else {
98  Option<RangeDefinition> dim_range = ranges[idx_def.variable()];
99  assert(dim_range);
100  init_values.push_back(idx_def.constant() + idx_def.factor() * dim_range->begin());
101  }
102  }
103  }
104  return init_values;
105 }
106 
107 int Index::dimension() { return _indexes.size(); }
108 
109 Expression Index::expression() const { return _exp; }
110 
111 void Index::setMap(Expression exp) {}
112 
113 bool Index::hasMap() const { return false; }
114 
115 bool Index::operator==(const Index& other) const { return false; }
116 
117 bool Index::isConstant() const
118 {
119  if (isEmpty()) {
120  return false;
121  }
122  CheckIndexExpression constant_index;
123  return constant_index.apply(_exp.expression());
124 }
125 
127 {
128  _exp = exp;
129  parseIndexes();
130 }
131 
132 string Index::identifier(bool recursive_use) const
133 {
134  stringstream buffer;
135  if (isConstant() && !recursive_use) {
136  buffer << "_eval" << _exp;
137  } else {
138  buffer << variable();
139  }
140  return buffer.str();
141 }
142 
144 {
146  assert(var);
147  return var.get();
148 }
149 
150 Range Index::range() const { return Range(variable()); }
151 
152 Index Index::revert() const
153 {
154  RevertIndex revert;
155  return Index(Expression(revert.apply(_exp.expression())));
156 }
157 
158 Index Index::replace(bool range_idx) const { return replace(range(), range_idx); }
159 
160 Index Index::replace(Option<Range> for_range, bool range_idx) const
161 {
162  Range var_range = range();
163  if (for_range) {
164  ReplaceIndex replace = ReplaceIndex(for_range.get(), _exp.expression(), range_idx);
165  return Index(Expression(replace.apply(_exp.expression())));
166  }
167  ReplaceIndex replace = ReplaceIndex(var_range, _exp.expression(), range_idx);
168  return Index(Expression(replace.apply(_exp.expression())));
169 }
170 
171 string Index::usageExp() const { return _exp.usage(); }
172 
173 string Index::modelicaExp() const
174 {
175  stringstream buffer;
176  string usage_exp = _exp.usage();
177  buffer << variable().name();
178  if (!usage_exp.empty()) {
179  buffer << "[" << usage_exp << "]";
180  }
181  return buffer.str();
182 }
183 
184 string Index::print() const
185 {
186  stringstream buffer;
188  PartialEvalExp partial_eval;
189  Expression exp = Expression(partial_eval.apply(_exp.expression()));
190  buffer << "_idx" << exp;
191  return buffer.str();
192 }
193 
194 vector<string> Index::variables()
195 {
196  vector<string> vars;
197  for (unsigned int i = 0; i < _indexes.size(); i++) {
198  if (_indexes[i].variable().empty()) {
199  stringstream constant;
200  constant << _indexes[i].constant();
201  vars.push_back(constant.str());
202  } else {
203  vars.push_back(_indexes[i].variable());
204  }
205  }
206  return vars;
207 }
208 
209 bool Index::hasVariable(int dim) { return !_indexes[dim].variable().empty(); }
210 
211 string Index::variable(int dim) { return _indexes[dim].variable(); }
212 
213 bool Index::hasFactor(int dim) { return _indexes[dim].factor() != 1; }
214 
215 int Index::factor(int dim) { return _indexes[dim].factor(); }
216 
217 bool Index::hasConstant(int dim) { return _indexes[dim].constant() != 0; }
218 
219 int Index::constant(int dim) { return _indexes[dim].constant(); }
220 
221 bool Index::isEmpty() const { return _exp.isEmpty(); }
222 
223 std::ostream& operator<<(std::ostream& out, const Index& i)
224 {
225  out << i.print();
226  return out;
227 }
228 
229 RangeDefinition::RangeDefinition(int begin, int end, int step) : _begin(begin), _end(end), _step(step), _begin_exp(), _end_exp() {}
230 
231 RangeDefinition::RangeDefinition(Expression begin_exp, Expression end_exp, int begin, int end, int step)
232  : _begin(begin), _end(end), _step(step), _begin_exp(begin_exp), _end_exp(end_exp)
233 {
234 }
235 
236 void RangeDefinition::setBegin(int begin) { _begin = begin; }
237 
238 void RangeDefinition::setEnd(int end) { _end = end; }
239 
240 string RangeDefinition::generateExp(Expression exp, int limit, bool convert_params) const
241 {
242  stringstream code;
243  if (exp.isEmpty()) {
244  code << limit;
245  } else {
246  Index index(exp);
247  if (convert_params) {
248  index = index.replace();
249  }
250  code << index.expression();
251  }
252  return code.str();
253 }
254 
255 string RangeDefinition::beginExp(bool convert_params, bool c_index) const
256 {
257  return generateExp(_begin_exp, ((c_index) ? cBegin() : begin()), convert_params);
258 }
259 
260 string RangeDefinition::endExp(bool convert_params, bool c_index) const
261 {
262  return generateExp(_end_exp, ((c_index) ? cEnd() : end()), convert_params);
263 }
264 
265 Range::Range() : _ranges(), _index_pos(), _size(1), _type(RANGE::For), _fixed(true), _merged_dims(false) {}
266 
267 Range::Range(AST_Equation_For eqf, RANGE::Type type) : _ranges(), _index_pos(), _size(1), _type(type), _fixed(true), _merged_dims(false)
268 {
269  AST_ForIndexList fil = eqf->forIndexList();
270  setRangeDefinition(fil);
271 }
272 
273 Range::Range(AST_Statement_For stf, RANGE::Type type, bool from_event)
274  : _ranges(), _index_pos(), _size(1), _type(type), _fixed(true), _merged_dims(false)
275 {
276  AST_ForIndexList fil = stf->forIndexList();
277  setRangeDefinition(fil, from_event);
278 }
279 
280 Range::Range(Variable var, RANGE::Type type) : _ranges(), _index_pos(), _size(1), _type(type), _fixed(true), _merged_dims(false)
281 {
282  generate(var);
283 }
284 
285 Range::Range(AST_Expression exp) : _ranges(), _index_pos(), _size(1), _type(RANGE::For), _fixed(true), _merged_dims(false)
286 {
287  generate(exp);
288 }
289 
290 Range::Range(SB::Set set, int offset, vector<string> vars, Option<Range> orig_range)
291  : _ranges(), _index_pos(), _size(1), _type(RANGE::For), _fixed(true), _merged_dims(false)
292 {
293  generate(set, offset, vars, orig_range);
294 }
295 
296 void Range::updateRangeDefinition(std::string index_def, RangeDefinition def, int pos)
297 {
298  _ranges.insert(index_def, def);
299  _index_pos.insert(index_def, pos);
300  Option<RangeDefinition> range = _ranges[index_def];
301  assert(range);
302  _size *= range->size();
303  _row_size.push_back(range->size());
304  Variable vi(newType_Integer(), TP_FOR, nullptr, nullptr, vector<int>(1, 1), false);
305  ModelConfig::instance().addVariable(index_def, vi);
306 }
307 
308 bool Range::testExpression(AST_Expression exp)
309 {
310  if (exp->expressionType() == EXPCOMPREF) {
311  AST_Expression_ComponentReference cr = exp->getAsComponentReference();
312  Option<Variable> var = ModelConfig::instance().lookup(cr->name());
313  if (!var) {
314  Error::instance().add(exp->lineNum(), EM_IR | EM_VARIABLE_NOT_FOUND, ER_Error, "index.cpp:264 %s", cr->name().c_str());
315  return false;
316  }
317  if (var->isParameter()) {
318  _fixed = false;
319  return true;
320  }
321  }
322  return false;
323 }
324 
325 void Range::setRangeDefinition(AST_ForIndexList fil, bool from_event)
326 {
327  AST_ForIndexListIterator filit;
328  int pos = 0;
329  foreach (filit, fil) {
330  AST_ForIndex fi = current_element(filit);
331  AST_Expression in = fi->in_exp();
332  AST_ExpressionList el = in->getAsRange()->expressionList();
333  EvalInitExp eval;
334  int size = el->size();
335  AST_Expression ast_begin_exp = AST_ListFirst(el);
336  AST_Expression ast_end_exp = AST_ListAt(el, size - 1);
337  Expression begin_exp;
338  Expression end_exp;
339  int begin = 1;
340  int end = 1;
341  if (testExpression(ast_begin_exp)) {
342  begin_exp = Expression(ast_begin_exp);
343  } else {
344  begin = eval.apply(ast_begin_exp);
345  }
346  if (testExpression(ast_end_exp)) {
347  end_exp = Expression(ast_end_exp);
348  } else {
349  end = eval.apply(ast_end_exp);
350  }
351  if (from_event) {
352  end = eval.apply(ast_end_exp) - begin + 1;
353  begin = 1;
354  }
355  if (end < begin) {
356  Error::instance().add(AST_ListFirst(el)->lineNum(), EM_IR | EM_WRONG_EXP, ER_Fatal, "Wrong equation range.");
357  }
358  string index = fi->variable()->c_str();
359  updateRangeDefinition(index,
360  (size == 2 ? RangeDefinition(begin_exp, end_exp, begin, end)
361  : RangeDefinition(begin_exp, end_exp, begin, end, eval.apply(AST_ListAt(el, 1)))),
362  pos++);
363  }
364 }
365 
366 void Range::generate(Variable var)
367 {
368  int pos = 0;
369  for (unsigned int i = 0; i < var.dimensions(); i++) {
370  string index = getDimensionVar(i + 1);
371  int begin = 1;
372  int end = var.size(i);
373  updateRangeDefinition(index, RangeDefinition(begin, end), pos++);
374  }
375 }
376 
377 void Range::generate(AST_Expression exp)
378 {
379  assert(exp->expressionType() == EXPCOMPREF);
380  CheckIndexExpression constant_index;
381  assert(constant_index.apply(exp));
382  AST_Expression_ComponentReference ref = exp->getAsComponentReference();
383  assert(ref->hasIndexes());
384  AST_ExpressionList indexes = ref->firstIndex();
385  AST_ExpressionListIterator it;
386  int i = 0;
387  int pos = 0;
388  foreach (it, indexes) {
389  AST_Expression index_exp = current_element(it);
390  string index = getDimensionVar(i + 1);
391  EvalInitExp eval_exp;
392  int scalar_value = eval_exp.apply(index_exp);
393  updateRangeDefinition(index, RangeDefinition(scalar_value, scalar_value), pos++);
394  }
395 }
396 
397 bool Range::isVariable(std::string var)
398 {
399  bool not_number = true;
400  try {
401  std::stoi(var);
402  not_number = false;
403  } catch (const std::exception&) {
404  }
405  return not_number;
406 }
407 
408 Expression Range::getExp(std::vector<Expression> exps, size_t pos)
409 {
410  if (exps.empty()) {
411  return Expression();
412  }
413  assert(exps.size() > pos);
414  _fixed = false;
415  return exps[pos];
416 }
417 
418 void Range::generate(SB::Set set, int offset, vector<string> vars, Option<Range> orig_range)
419 {
420  unsigned int pos = 0;
421  const bool MAP_RANGE = orig_range.has_value();
422  SB::UnordAtomSet a_sets = set.atomicSets();
423  for (SB::AtomSet a_set : a_sets) {
424  SB::MultiInterval intervals = a_set.atomicSets();
425  int exp_pos = 0;
426  for (SB::Interval interval : intervals.intervals()) {
427  int begin = interval.lo() - offset + 1;
428  int end = begin + interval.hi() - interval.lo();
429  int step = interval.step();
430  if (MAP_RANGE) {
431  RangeDefinition orig_def = orig_range->definition().value(exp_pos);
432  begin = orig_def.begin() + (begin - 1) * orig_def.step();
433  end = orig_def.begin() + (end - 1) * orig_def.step();
434  }
435  if (end < begin) {
436  Error::instance().add(0, EM_IR | EM_UNKNOWN_ODE, ER_Error, "Wrong range in dependency matrix.");
437  }
438  string index = Utils::instance().iteratorVar(pos);
439  if (!vars.empty() && pos < vars.size() && isVariable(vars[pos])) {
440  index = vars[pos];
441  }
442  updateRangeDefinition(index, RangeDefinition(begin, end, step), pos++);
443  exp_pos++;
444  }
445  }
446 }
447 
448 void Range::generate(SB::Set set, int offset, vector<string> vars, std::vector<Expression> begin_exps, std::vector<Expression> end_exps)
449 {
450  unsigned int pos = 0;
451  SB::UnordAtomSet a_sets = set.atomicSets();
452  for (SB::AtomSet a_set : a_sets) {
453  SB::MultiInterval intervals = a_set.atomicSets();
454  int exp_pos = 0;
455  for (SB::Interval interval : intervals.intervals()) {
456  int begin = interval.lo() - offset + 1;
457  int end = begin + interval.hi() - interval.lo();
458  if (end < begin) {
459  Error::instance().add(0, EM_IR | EM_UNKNOWN_ODE, ER_Error, "Wrong range in dependency matrix.");
460  }
461  string index = Utils::instance().iteratorVar(pos);
462  if (!vars.empty() && pos < vars.size() && isVariable(vars[pos])) {
463  index = vars[pos];
464  }
465  updateRangeDefinition(index, RangeDefinition(getExp(begin_exps, exp_pos), getExp(end_exps, exp_pos), begin, end), pos++);
466  exp_pos++;
467  }
468  }
469 }
470 
471 string Range::iterator(int dim, bool range_idx)
472 {
473  if (range_idx) {
474  return getDimensionVar(dim + 1, range_idx);
475  }
476  for (auto ip : _index_pos) {
477  if (ip.second == dim) {
478  return ip.first;
479  }
480  }
481  return getDimensionVar(dim + 1);
482 }
483 
484 string Range::iterator(string var, int dim, bool range_idx)
485 {
486  if (isDimensionVar(var)) {
487  iterator(dim, range_idx);
488  }
489  for (auto ip : _index_pos) {
490  if (ip.first == var) {
491  return getDimensionVar(ip.second + 1);
492  }
493  }
494  return iterator(dim, range_idx);
495 }
496 
497 bool Range::isDimensionVar(string var) { return (var.rfind("_d", 0) == 0); }
498 
500 {
501  stringstream buffer;
502  int size = _ranges.size();
503  for (int i = 1; i <= size; i++) {
504  buffer << "%d" << (i + 1 <= size ? "," : "");
505  }
506  return buffer.str();
507 }
508 
509 string Range::getDimensionVarsString(bool range) const
510 {
511  stringstream buffer;
512  int size = _ranges.size();
513  for (int i = 1; i <= size; i++) {
514  buffer << getDimensionVar(i, range) << (i + 1 <= size ? "," : "");
515  }
516  return buffer.str();
517 }
518 
519 vector<string> Range::getDimensionVars(bool range) const
520 {
521  vector<string> buffer;
522  int size = _ranges.size();
523  for (int i = 1; i <= size; i++) {
524  buffer.push_back(getDimensionVar(i, range));
525  }
526  return buffer;
527 }
528 
529 string Range::getDimensionVar(int i, bool range) const
530 {
531  stringstream buffer;
532  if (range) {
533  buffer << "_rg";
534  }
535  buffer << "_d" << i;
536  if (range) {
537  addRangeVariables(i, buffer.str());
538  }
539  return buffer.str();
540 }
541 
542 string Range::end() const
543 {
544  stringstream buffer;
545  int size = _ranges.size();
546  for (int i = size; i > 0; i--) {
547  buffer << block(i - 1) << "}" << (i - 1 > 0 ? "\n" : "");
548  }
549  return buffer.str();
550 }
551 
552 string Range::print(bool range, bool c_index, bool convert_params) const
553 {
554  stringstream buffer;
555  RangeDefinitionTable ranges = _ranges;
557  string block = "";
558  int idx_count = 0;
559  vector<string> idxs = getIndexes();
560  if (range) {
561  idxs = getDimensionVars(range);
562  }
563  for (RangeDefinition r = ranges.begin(it); !ranges.end(it); r = ranges.next(it)) {
564  if (_type == RANGE::For) {
565  string idx = idxs[idx_count];
566  buffer << block << "for(" << idx << " = " << r.beginExp(convert_params, c_index) << "; ";
567  buffer << idx << "<=" << r.endExp(convert_params, c_index) << "; ";
568  buffer << idx << "+=" << r.step() << ") {" << endl;
569  block += TAB;
570  idx_count++;
571  }
572  }
573  if (range) {
575  } else {
577  }
578  return buffer.str();
579 }
580 
581 string Range::indexes() const
582 {
583  stringstream buffer;
584  vector<string> indexes = getIndexes();
585  long unsigned int size = _ranges.size(), i = 0;
586  for (string index : indexes) {
587  buffer << index << (++i < size ? "," : "");
588  }
589  return buffer.str();
590 }
591 
592 vector<string> Range::getInitValues() const
593 {
594  vector<string> indexes;
595  RangeDefinitionTable ranges = _ranges;
597  for (RangeDefinition r = ranges.begin(it); !ranges.end(it); r = ranges.next(it)) {
598  stringstream val;
599  val << r.begin();
600  indexes.push_back(val.str());
601  }
602  return indexes;
603 }
604 
605 vector<string> Range::getIndexes() const
606 {
607  vector<string> indexes;
608  RangeDefinitionTable ranges = _ranges;
610  for (RangeDefinition r = ranges.begin(it); !ranges.end(it); r = ranges.next(it)) {
611  string var = ranges.key(it);
612  indexes.push_back(var);
613  }
614  return indexes;
615 }
616 
617 void Range::addLocalVariables() const
618 {
619  RangeDefinitionTable ranges = _ranges;
621  int i = 1;
622  for (RangeDefinition r = ranges.begin(it); !ranges.end(it); r = ranges.next(it)) {
623  string var = ranges.key(it);
624  ModelConfig::instance().addLocalSymbol("int " + var + ";");
626  }
627 }
628 
630 {
631  RangeDefinitionTable ranges = _ranges;
633  int i = 1;
634  for (RangeDefinition r = ranges.begin(it); !ranges.end(it); r = ranges.next(it)) {
635  string index = getDimensionVar(i++, true);
636  ModelConfig::instance().addLocalSymbol("int " + index + ";");
637  }
638 }
639 
640 void Range::addRangeVariables(int i, string index) const
641 {
642  Variable range_var(newType_Integer(), TP_FOR, nullptr, nullptr, vector<int>(1, 1), false);
643  ModelConfig::instance().addVariable(index, range_var);
644 }
645 
646 int Range::rowSize(int dim) const
647 {
648  int total = 1;
649  for (int it = _row_size.size() - 1; it > dim; it--) {
650  total *= _row_size.at(it);
651  }
652  return total;
653 }
654 
655 string Range::block(int dim) const
656 {
657  int size = _ranges.size();
658  if (dim >= 0) {
659  size = dim;
660  }
661  string block = "";
662  for (int i = 0; i < size; i++) {
663  block += TAB;
664  }
665  return block;
666 }
667 
668 int Range::pos(string var)
669 {
670  Option<int> p = _index_pos[var];
671  if (p) {
672  return boost::get<int>(p);
673  }
674  return 0;
675 }
676 
678 {
679  int dimension = usage.dimension();
680  assert(_ranges.size() == dimension);
682  int i = 0;
683  for (RangeDefinition r = _ranges.begin(it); !_ranges.end(it); r = _ranges.next(it), i++) {
684  if (usage.hasVariable(i)) {
685  int new_begin = r.begin() * usage.factor(i) + usage.constant(i);
686  int new_end = r.end() * usage.factor(i) + usage.constant(i);
687  RangeDefinition new_range(new_begin, new_end, r.step());
688  _ranges.insert(_ranges.key(it), new_range);
689  }
690  }
691 }
692 
693 void Range::update(int offset)
694 {
696  int i = 0;
697  map<string, RangeDefinition> updated_ranges;
698  for (RangeDefinition r = _ranges.begin(it); !_ranges.end(it); r = _ranges.next(it), i++) {
699  int new_begin = r.begin() + offset;
700  int new_end = r.end() + offset;
701  RangeDefinition new_range(new_begin, new_end, r.step());
702  updated_ranges[_ranges.key(it)] = new_range;
703  }
704  for (auto update_range : updated_ranges) {
705  _ranges.insert(update_range.first, update_range.second);
706  }
707 }
708 
709 void Range::update(Range other)
710 {
713  RangeDefinitionTable other_ranges = other.definition();
714  assert(other_ranges.size() == _ranges.size());
715  map<string, RangeDefinition> updated_ranges;
716  RangeDefinition other_def = other_ranges.begin(other_it);
717  for (RangeDefinition r = _ranges.begin(it); !_ranges.end(it); r = _ranges.next(it), other_def = other_ranges.next(other_it)) {
718  int new_begin = r.begin() + other_def.begin() - 1;
719  int new_end = r.end() + other_def.begin() - 1;
720  RangeDefinition new_range(new_begin, new_end, r.step());
721  updated_ranges[_ranges.key(it)] = new_range;
722  }
723  for (auto update_range : updated_ranges) {
724  _ranges.insert(update_range.first, update_range.second);
725  }
726 }
727 
729 {
730  int dimension = def.dimension();
731  assert(_ranges.size() == dimension);
732  assert(usage.isConstant());
734  int i = 0;
735  for (RangeDefinition r = _ranges.begin(it); !_ranges.end(it); r = _ranges.next(it), i++) {
736  if (def.hasVariable(i)) {
737  int new_begin = r.begin() * def.factor(i) + def.constant(i);
738  int new_end = r.end() * def.factor(i) + def.constant(i);
739  int usage_val = usage.constant(i);
740  if (usage_val < new_begin || usage_val > new_end) {
741  return false;
742  }
743  }
744  }
745  return true;
746 }
747 
748 string Range::in(ExpressionList exps)
749 {
750  vector<string> str_exps;
751  for (auto e : exps) {
752  str_exps.push_back(e.print());
753  }
754  return in(str_exps);
755 }
756 
757 string Range::in(vector<string> exps)
758 {
759  assert(exps.size() <= (size_t)_ranges.size());
760  // If empty generate a default true condition to handle scalar cases.
761  if (exps.empty()) {
762  return "1";
763  }
764  stringstream code;
766  int i = 0;
767  int size = _ranges.size();
768  int exps_size = exps.size();
769  for (RangeDefinition r = _ranges.begin(it); !_ranges.end(it); r = _ranges.next(it), i++) {
770  string exp_str = (i < exps_size) ? exps[i] : getDimensionVar(i);
771 
772  code << "(" << r.begin() << " <= " << exp_str << " && " << exp_str << " <= " << r.end() << ")";
773  code << ((i + 1 < size) ? " && " : "");
774  }
775  return code.str();
776 }
777 
778 int Range::size() const { return _size; };
779 
780 bool Range::isEmpty() const { return _row_size.size() == 0; };
781 
782 map<std::string, AST_Expression> Range::initExps()
783 {
784  map<string, AST_Expression> init_exps;
786  int i = 0;
787  for (RangeDefinition r = _ranges.begin(it); !_ranges.end(it); r = _ranges.next(it), i++) {
788  init_exps[_ranges.key(it)] = newAST_Expression_Integer(r.begin());
789  }
790  return init_exps;
791 }
792 
793 bool Range::checkRangeVariable(string var, set<string>& added_vars, vector<string>& old_keys, int& pos)
794 {
795  if (added_vars.find(var) == added_vars.end()) {
797  if (r.has_value()) {
798  added_vars.insert(var);
799  string index = getDimensionVar(pos);
800  if (index != var) {
801  old_keys.push_back(var);
802  _ranges.insert(index, r.get());
803  }
804  pos++;
805  return true;
806  }
807  }
808  return false;
809 }
810 
811 bool Range::checkRangeVariables(string ife_idx, string ifr_idx, set<string>& added_vars, vector<string>& old_keys, int& pos)
812 {
813  if ((!isVariable(ife_idx) || ife_idx.empty()) && (!isVariable(ifr_idx) || ifr_idx.empty())) {
814  return true;
815  }
816  bool found = false;
817  if (isVariable(ife_idx)) {
818  found = checkRangeVariable(ife_idx, added_vars, old_keys, pos);
819  }
820  if (!found && isVariable(ifr_idx)) {
821  found = checkRangeVariable(ifr_idx, added_vars, old_keys, pos);
822  }
823  return found;
824 }
825 
826 void Range::replace(Index ife_usage, Index ifr_usage)
827 {
828  const bool SELECT_IFE_USAGE = ife_usage.variables().size() > ifr_usage.variables().size();
829  vector<string> max_usage = (SELECT_IFE_USAGE) ? ife_usage.variables() : ifr_usage.variables();
830  vector<string> min_usage = (!SELECT_IFE_USAGE) ? ife_usage.variables() : ifr_usage.variables();
831  vector<pair<string, string>> used_variables;
832 
833  int min_usage_idx = 0;
834  int min_usage_size = min_usage.size();
835  for (string max_usage_str : max_usage) {
836  string min_usage_str = "";
837  if (min_usage_idx < min_usage_size) {
838  min_usage_str = min_usage[min_usage_idx];
839  }
840  used_variables.push_back(make_pair(max_usage_str, min_usage_str));
841  min_usage_idx++;
842  }
843 
844  // Add only variables from the ifr index that are higher than the ife usage
845  // the rest should be replaced by variables in the original range.
846  /*int variables_size = variables.size();
847  int ifr_vars = 1;
848  if (!ifr_usage.isEmpty()) {
849  for (string ifr_var : ifr_usage.variables()) {
850  if (ifr_vars > variables_size) {
851  variables.push_back(ifr_var);
852  }
853  ifr_vars++;
854  }
855  sort(variables.begin(), variables.end());
856  variables.erase(unique(variables.begin(), variables.end()), variables.end());
857  }*/
858  // In case of a scalar usage in N<->1 relations.
859  if (used_variables.empty()) {
860  max_usage = getIndexes();
861  for (string max_usage_str : max_usage) {
862  string min_usage_str = "";
863  used_variables.push_back(make_pair(max_usage_str, min_usage_str));
864  }
865  }
866  set<string> added_vars;
867  vector<string> old_keys;
868  int pos = 1;
869  for (pair<string, string> vars : used_variables) {
870  assert(checkRangeVariables(vars.first, vars.second, added_vars, old_keys, pos));
871  }
872  for (string key : old_keys) {
873  _ranges.remove(key);
874  }
875 }
876 
877 bool Range::fixed() const { return _fixed; }
878 
879 void Range::merge(Range other)
880 {
882  int pos = _ranges.size();
883  for (RangeDefinition r = other._ranges.begin(it); !other._ranges.end(it); r = other._ranges.next(it)) {
884  updateRangeDefinition(other._ranges.key(it), RangeDefinition(r.begin(), r.end(), r.step()), pos++);
885  }
886  _merged_dims = true;
887 }
888 
889 int Range::dim() const { return _ranges.size(); }
890 
891 bool Range::hasMergedDims() const { return _merged_dims; }
892 
893 std::ostream& operator<<(std::ostream& out, const Range& r) { return out << r.print(); }
894 
895 } // namespace IR
896 } // namespace MicroModelica
MicroModelica::IR::Range::end
std::string end() const
Definition: index.cpp:559
equation.hpp
MicroModelica::Util::ModelConfig::lookup
Option< Variable > lookup(std::string var_name)
Definition: model_config.hpp:125
MicroModelica::IR::RangeDefinition::_begin_exp
Expression _begin_exp
Definition: index.hpp:158
MicroModelica::IR::Range
Definition: index.hpp:164
MicroModelica::IR::Index::hasFactor
bool hasFactor(int dim)
Definition: index.cpp:230
MicroModelica::IR::Index::initValues
std::vector< int > initValues(Option< Range > range)
Definition: index.cpp:94
MicroModelica::IR::IndexDefinition::variable
std::string variable()
Definition: index.cpp:70
MicroModelica::Util::Error::instance
static Error & instance()
Definition: error.hpp:128
MicroModelica::IR::Range::addLocalVariables
void addLocalVariables() const
Definition: index.cpp:634
ModelTable< std::string, RangeDefinition >
MicroModelica::IR::Index::setExp
void setExp(Expression exp)
Definition: index.cpp:143
MicroModelica::IR::Expression::usage
std::string usage() const
Definition: expression.cpp:101
ModelTable::begin
iterator begin()
Definition: table.hpp:68
ast_builder.hpp
MicroModelica::IR::operator<<
std::ostream & operator<<(std::ostream &out, const Equation &e)
Definition: equation.cpp:185
EXPCOMPREF
@ EXPCOMPREF
Definition: ast_types.hpp:165
usage
void usage()
Definition: main.cpp:48
MicroModelica::Util::VarSymbolTable
Definition: symbol_table.hpp:184
MicroModelica::Util::ModelConfig::symbols
VarSymbolTable & symbols()
Definition: model_config.hpp:122
MicroModelica::Util::Variable
Definition: symbol_table.hpp:75
MicroModelica::IR::Expression::reference
Option< Util::Variable > reference() const
Definition: expression.cpp:94
index.hpp
MicroModelica::IR::Range::_fixed
bool _fixed
Definition: index.hpp:235
MicroModelica::IR::RangeDefinition::RangeDefinition
RangeDefinition()
Definition: index.hpp:138
MicroModelica::IR::Range::initExps
map< std::string, AST_Expression > initExps()
Definition: index.cpp:799
MicroModelica::IR::RangeDefinition::begin
int begin() const
Definition: index.hpp:142
MicroModelica::IR::Range::getPrintDimensionVarsString
std::string getPrintDimensionVarsString() const
Definition: index.cpp:516
MicroModelica::IR::Index::print
std::string print() const
Definition: index.cpp:201
MicroModelica::IR::Index::range
Range range() const
Definition: index.cpp:167
MicroModelica::IR::Range::_ranges
RangeDefinitionTable _ranges
Definition: index.hpp:230
MicroModelica::IR::Range::applyUsage
void applyUsage(Index usage)
Definition: index.cpp:694
MicroModelica::IR::Expression::expression
AST_Expression expression() const
Definition: expression.hpp:87
MicroModelica::IR::Range::addRangeLocalVariables
void addRangeLocalVariables() const
Definition: index.cpp:646
MicroModelica::IR::Range::_type
RANGE::Type _type
Definition: index.hpp:233
MicroModelica::IR::Index::constant
int constant(int dim)
Definition: index.cpp:236
MicroModelica::IR::IndexDefinition::IndexDefinition
IndexDefinition()
Definition: index.cpp:62
MicroModelica::IR::Index::operator==
bool operator==(const Index &other) const
Definition: index.cpp:132
MicroModelica::IR::RangeDefinition::endExp
std::string endExp(bool convert_params, bool c_index) const
Definition: index.cpp:277
ModelTable::key
Key key(iterator &it)
Definition: table.hpp:94
MicroModelica::IR::Index::isEmpty
bool isEmpty() const
Definition: index.cpp:238
MicroModelica::IR::RangeDefinition::_end_exp
Expression _end_exp
Definition: index.hpp:159
helpers.hpp
MicroModelica::IR::Range::print
std::string print(bool range=false, bool c_index=false, bool convert_params=false) const
Definition: index.cpp:569
Option
Definition: util_types.hpp:32
MicroModelica::IR::Range::generate
void generate(SB::Set set, int offset, std::vector< std::string > vars, std::vector< Expression > begin_exps=std::vector< Expression >(), std::vector< Expression > end_exps=std::vector< Expression >())
MicroModelica::IR::Range::pos
int pos(std::string var)
Definition: index.cpp:685
MicroModelica::Util::Variable::name
string name() const
Definition: symbol_table.hpp:127
newType_Integer
Type_Integer newType_Integer()
Definition: type.cpp:56
MicroModelica::IR::IndexDefinition::constant
int constant()
Definition: index.cpp:66
MicroModelica::IR::Range::fixed
bool fixed() const
Definition: index.cpp:894
MicroModelica::IR::Index::variables
std::vector< std::string > variables()
Definition: index.cpp:211
MicroModelica::Util::ModelConfig::addVariable
void addVariable(VarName name, Variable var)
Definition: model_config.hpp:134
MicroModelica::Util::ER_Fatal
@ ER_Fatal
ER_Fatal.
Definition: error.hpp:123
MicroModelica::IR::Index::revert
Index revert() const
Definition: index.cpp:169
model_config.hpp
MicroModelica::IR::RangeDefinition::cEnd
int cEnd() const
Definition: index.hpp:145
MicroModelica::IR::Range::merge
void merge(Range other)
Definition: index.cpp:896
MicroModelica::IR::Range::rowSize
int rowSize(int dim) const
Definition: index.cpp:663
MicroModelica::IR::Index::hasMap
bool hasMap() const
Definition: index.cpp:130
MicroModelica::IR::Range::definition
RangeDefinitionTable definition() const
Definition: index.hpp:177
MicroModelica::IR::Range::getExp
Expression getExp(std::vector< Expression > exps, size_t pos)
Definition: index.cpp:425
MicroModelica::IR::Range::testExpression
bool testExpression(AST_Expression exp)
Definition: index.cpp:325
MicroModelica::Util::ModelConfig::addLocalSymbol
void addLocalSymbol(std::string symbol)
Definition: model_config.hpp:126
MicroModelica::IR::IndexDefinition::_variable
string _variable
Definition: index.hpp:87
MicroModelica::IR::Expression
Definition: expression.hpp:64
MicroModelica::IR::Range::Range
Range()
Definition: index.cpp:282
MicroModelica::IR::IndexDefinition::_factor
int _factor
Definition: index.hpp:89
MicroModelica::IR::ExpressionList
list< Expression > ExpressionList
Definition: expression.hpp:95
MicroModelica::Util::ER_Error
@ ER_Error
ER_Error.
Definition: error.hpp:122
ModelTable::end
iterator end()
Definition: table.hpp:70
MicroModelica::IR::Index::factor
int factor(int dim)
Definition: index.cpp:232
MicroModelica::IR::Index::_exp
Expression _exp
Definition: index.hpp:129
MicroModelica::IR::IndexDefinition::factor
int factor()
Definition: index.cpp:68
MicroModelica::IR::Range::isDimensionVar
bool isDimensionVar(std::string var)
Definition: index.cpp:514
ModelTable::remove
void remove(Key k)
Definition: table.hpp:60
TP_FOR
@ TP_FOR
Definition: ast_types.hpp:201
MicroModelica::IR::Range::_size
int _size
Definition: index.hpp:232
MicroModelica::IR::Index::dimension
int dimension()
Definition: index.cpp:124
MicroModelica::Util::Error::add
void add(int pos, unsigned int code, ER_Type t, const std::string message,...)
Definition: error.cpp:42
MicroModelica::IR::Index::isConstant
bool isConstant() const
Definition: index.cpp:134
MicroModelica::IR::Range::addRangeVariables
void addRangeVariables(int i, string index) const
Definition: index.cpp:657
MicroModelica::IR::Range::getDimensionVars
std::vector< std::string > getDimensionVars(bool range=false) const
Definition: index.cpp:536
MicroModelica::IR::Range::block
std::string block(int dim=-1) const
Definition: index.cpp:672
MicroModelica::IR::RangeDefinition::beginExp
std::string beginExp(bool convert_params, bool c_index) const
Definition: index.cpp:272
MicroModelica::IR::Range::getDimensionVarsString
std::string getDimensionVarsString(bool range=false) const
Definition: index.cpp:526
MicroModelica::IR::FunctionPrinter::parseIndexes
std::map< std::string, std::string > parseIndexes(string var, Option< Range > range, int offset, bool modelica_index=true) const
Definition: helpers.cpp:330
TAB
#define TAB
Definition: util.hpp:79
MicroModelica::IR::Index::parseIndexes
void parseIndexes()
Definition: index.cpp:74
ModelTable< std::string, RangeDefinition >::iterator
std::map< std::string, RangeDefinition >::iterator iterator
Definition: table.hpp:61
MicroModelica::IR::Range::iterator
std::string iterator(int dim, bool range_idx=false)
Definition: index.cpp:488
MicroModelica::Util::ModelConfig::instance
static ModelConfig & instance()
Definition: model_config.hpp:87
EM_VARIABLE_NOT_FOUND
#define EM_VARIABLE_NOT_FOUND
Definition: error.hpp:71
MicroModelica::IR::Expression::isEmpty
bool isEmpty() const
Definition: expression.hpp:91
MicroModelica::IR::Range::checkRangeVariables
bool checkRangeVariables(string ife_idx, string ifr_idx, set< string > &added_vars, vector< string > &old_keys, int &pos)
Definition: index.cpp:828
MicroModelica::IR::Index::Index
Index()
Definition: index.hpp:94
MicroModelica::IR::IndexDefinition::_constant
int _constant
Definition: index.hpp:88
AST_ListFirst
T1 AST_ListFirst(list< T1 > *l)
Definition: ast_types.hpp:271
MicroModelica::IR::RangeDefinition::_end
int _end
Definition: index.hpp:156
MicroModelica::IR::RangeDefinition::generateExp
std::string generateExp(Expression exp, int limit, bool convert_params) const
Definition: index.cpp:257
MicroModelica::IR::Index::usageExp
std::string usageExp() const
Definition: index.cpp:188
MicroModelica::IR::IndexDefinition
Definition: index.hpp:77
MicroModelica::IR::Range::isEmpty
bool isEmpty() const
Definition: index.cpp:797
MicroModelica::IR::Range::in
std::string in(ExpressionList exps)
Definition: index.cpp:765
MicroModelica::IR::RANGE::Type
Type
Definition: index.hpp:85
MicroModelica::IR::Range::setRangeDefinition
void setRangeDefinition(AST_ForIndexList fil, bool from_event=false)
Definition: index.cpp:342
MicroModelica::IR::Index
Definition: index.hpp:92
MicroModelica::IR::RangeDefinition::cBegin
int cBegin() const
Definition: index.hpp:143
AST_ListAt
T1 AST_ListAt(list< T1 > *l1, int i)
Definition: ast_types.hpp:298
MicroModelica::Generator::MODEL_INSTANCE::Component::Deps
@ Deps
MicroModelica::IR::RangeDefinition::setBegin
void setBegin(int begin)
Definition: index.cpp:253
MicroModelica::IR::Index::replace
Index replace(bool range_idx=false) const
Definition: index.cpp:175
MicroModelica::IR::Range::indexes
std::string indexes() const
Definition: index.cpp:598
EM_IR
#define EM_IR
Definition: error.hpp:66
MicroModelica::IR::RangeDefinitionTable
ModelTable< std::string, RangeDefinition > RangeDefinitionTable
Definition: index.hpp:162
MicroModelica::IR::Index::setMap
void setMap(IR::Expression exp)
Definition: index.cpp:128
MicroModelica
Definition: files.cpp:45
MicroModelica::IR::RANGE::For
@ For
Definition: index.hpp:102
MicroModelica::IR::Range::checkUsage
bool checkUsage(Index usage, Index def)
Definition: index.cpp:745
MicroModelica::IR::Index::modelicaExp
std::string modelicaExp() const
Definition: index.cpp:190
MicroModelica::IR::RangeDefinition::end
int end() const
Definition: index.hpp:144
MicroModelica::IR::Range::_index_pos
ModelTable< std::string, int > _index_pos
Definition: index.hpp:231
MicroModelica::IR::Range::checkRangeVariable
bool checkRangeVariable(string var, set< string > &added_vars, vector< string > &old_keys, int &pos)
Definition: index.cpp:810
MicroModelica::Util::Utils::instance
static Utils & instance()
Definition: util.hpp:83
MicroModelica::Util::Utils::iteratorVar
std::string iteratorVar(int dim)
Definition: util.cpp:138
MicroModelica::IR::Range::size
int size() const
Definition: index.cpp:795
MicroModelica::IR::Range::_row_size
std::vector< int > _row_size
Definition: index.hpp:234
MicroModelica::IR::RangeDefinition::_begin
int _begin
Definition: index.hpp:155
MicroModelica::IR::RangeDefinition::setEnd
void setEnd(int end)
Definition: index.cpp:255
MicroModelica::IR::Index::identifier
std::string identifier(bool recursive_use=false) const
Definition: index.cpp:149
ModelTable::insert
void insert(Key k, Value v)
Definition: table.hpp:48
EM_UNKNOWN_ODE
#define EM_UNKNOWN_ODE
Definition: error.hpp:101
EM_WRONG_EXP
#define EM_WRONG_EXP
Definition: error.hpp:77
MicroModelica::IR::Index::variable
Util::Variable variable() const
Definition: index.cpp:160
MicroModelica::IR::Range::update
void update(int offset)
Definition: index.cpp:710
ModelTable::size
const int size() const
Definition: table.hpp:109
MicroModelica::IR::Index::hasConstant
bool hasConstant(int dim)
Definition: index.cpp:234
MicroModelica::IR::Range::getDimensionVar
std::string getDimensionVar(int i, bool range=false) const
Definition: index.cpp:546
MicroModelica::IR::Index::hasVariable
bool hasVariable(int dim)
Definition: index.cpp:226
MicroModelica::IR::Range::updateRangeDefinition
void updateRangeDefinition(std::string index_def, RangeDefinition def, int pos)
Definition: index.cpp:313
MicroModelica::IR::Range::replace
void replace(Index ife_usage, Index ifr_usage=Index())
Definition: index.cpp:843
MicroModelica::IR::Range::isVariable
bool isVariable(std::string var)
Definition: index.cpp:414
MicroModelica::IR::RangeDefinition::step
int step() const
Definition: index.hpp:146
MicroModelica::IR::Index::expression
Expression expression() const
Definition: index.cpp:126
MicroModelica::IR::Range::dim
int dim() const
Definition: index.cpp:906
MicroModelica::IR::Index::_indexes
map< int, IndexDefinition > _indexes
Definition: index.hpp:128
MicroModelica::IR::RangeDefinition
Definition: index.hpp:136
newAST_Expression_Integer
AST_Expression newAST_Expression_Integer(int i)
Definition: ast_builder.cpp:130
MicroModelica::IR::Range::hasMergedDims
bool hasMergedDims() const
Definition: index.cpp:908
MicroModelica::IR::Range::_merged_dims
bool _merged_dims
Definition: index.hpp:236
current_element
#define current_element(it)
Definition: ast_types.hpp:34
util.hpp
MicroModelica::IR::Range::getInitValues
std::vector< std::string > getInitValues() const
Definition: index.cpp:609
error.hpp
ModelTable::next
Value next(iterator &it)
Definition: table.hpp:78
expression.hpp
MicroModelica::IR::Range::getIndexes
std::vector< std::string > getIndexes() const
Definition: index.cpp:622
statement.hpp