Debugger - Stage 1 (artf511247)
[deliverable/titan.core.git] / compiler2 / subtypestuff.cc
1 /******************************************************************************
2 * Copyright (c) 2000-2016 Ericsson Telecom AB
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * http://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors:
9 * Baji, Laszlo
10 * Balasko, Jeno
11 * Delic, Adam
12 * Raduly, Csaba
13 *
14 ******************************************************************************/
15 #include "subtypestuff.hh"
16 #include "../common/dbgnew.hh"
17 #include "Identifier.hh"
18 #include "Value.hh"
19 #include "Setting.hh"
20 #include "Type.hh"
21 #include "CompilerError.hh"
22 #include "Valuestuff.hh"
23 #include "ttcn3/TtcnTemplate.hh"
24 #include "ttcn3/Templatestuff.hh"
25 #include "ttcn3/PatternString.hh"
26 #include "PredefFunc.hh"
27
28 #include <limits.h>
29
30 namespace Common {
31
32
33 tribool operator||(tribool a, tribool b)
34 {
35 static tribool truth_table[3][3] = { {TFALSE, TUNKNOWN, TTRUE}, {TUNKNOWN, TUNKNOWN, TTRUE}, {TTRUE, TTRUE, TTRUE} };
36 return truth_table[a][b];
37 }
38
39 tribool operator&&(tribool a, tribool b)
40 {
41 static tribool truth_table[3][3] = { {TFALSE, TFALSE, TFALSE}, {TFALSE, TUNKNOWN, TUNKNOWN}, {TFALSE, TUNKNOWN, TTRUE} };
42 return truth_table[a][b];
43 }
44
45 tribool operator!(tribool tb)
46 {
47 static tribool truth_table[3] = { TTRUE, TUNKNOWN, TFALSE };
48 return truth_table[tb];
49 }
50
51 tribool TRIBOOL(bool b) { return ( b ? TTRUE : TFALSE ); }
52
53 string to_string(const tribool& tb)
54 {
55 switch (tb) {
56 case TFALSE:
57 return string("false");
58 case TTRUE:
59 return string("true");
60 case TUNKNOWN:
61 return string("unknown");
62 default:
63 FATAL_ERROR("print(tribool)");
64 }
65 return string();
66 }
67
68 ////////////////////////////////////////////////////////////////////////////////
69
70 const int_limit_t int_limit_t::minimum(int_limit_t::MINUS_INFINITY);
71
72 const int_limit_t int_limit_t::maximum(int_limit_t::PLUS_INFINITY);
73
74 int_limit_t::int_limit_t(int_limit_type_t p_type):
75 type(p_type)
76 {
77 switch (p_type) {
78 case MINUS_INFINITY:
79 case PLUS_INFINITY:
80 break;
81 default:
82 FATAL_ERROR("int_limit_t::int_limit_t(int_limit_type_t)");
83 }
84 }
85
86 bool int_limit_t::operator<(const int_limit_t& right) const
87 {
88 switch (type) {
89 case MINUS_INFINITY:
90 return (right.type!=MINUS_INFINITY);
91 case NUMBER:
92 return ( (right.type==PLUS_INFINITY) || ( (right.type==NUMBER) && (value<right.value) ) );
93 case PLUS_INFINITY:
94 return false;
95 default:
96 FATAL_ERROR("int_limit_t::operator<()");
97 }
98 }
99
100 bool int_limit_t::operator==(const int_limit_t& right) const
101 {
102 if (type==NUMBER) return ( (right.type==NUMBER) && (value==right.value) );
103 else return (type==right.type);
104 }
105
106 bool int_limit_t::is_adjacent(const int_limit_t& other) const
107 {
108 return ( (type==NUMBER) && (other.type==NUMBER) && ((value+1)==other.value) );
109 }
110
111 int_val_t int_limit_t::get_value() const
112 {
113 if (type!=NUMBER) FATAL_ERROR("int_limit_t::get_value()");
114 return value;
115 }
116
117 int_limit_t int_limit_t::next() const
118 {
119 return ( (type==NUMBER) ? int_limit_t(value+1) : *this );
120 }
121
122 int_limit_t int_limit_t::previous() const
123 {
124 return ( (type==NUMBER) ? int_limit_t(value-1) : *this );
125 }
126
127 void int_limit_t::check_single_value() const
128 {
129 if (type!=NUMBER) FATAL_ERROR("int_limit_t::check_single_value()");
130 }
131
132 void int_limit_t::check_interval_start() const
133 {
134 if (type==PLUS_INFINITY) FATAL_ERROR("int_limit_t::check_interval_start()");
135 }
136
137 void int_limit_t::check_interval_end() const
138 {
139 if (type==MINUS_INFINITY) FATAL_ERROR("int_limit_t::check_interval_end()");
140 }
141
142 string int_limit_t::to_string() const
143 {
144 switch (type) {
145 case int_limit_t::MINUS_INFINITY:
146 return string("-infinity");
147 case int_limit_t::NUMBER:
148 return value.t_str();
149 case int_limit_t::PLUS_INFINITY:
150 return string("infinity");
151 default:
152 FATAL_ERROR("int_limit_t::print()");
153 }
154 return string();
155 }
156
157 ////////////////////////////////////////////////////////////////////////////////
158
159 const size_limit_t size_limit_t::minimum(0);
160
161 const size_limit_t size_limit_t::maximum(INFINITE_SIZE);
162
163 bool size_limit_t::operator<(const size_limit_t& right) const
164 {
165 return ( !infinity && ( right.infinity || (size<right.size) ) );
166 }
167
168 bool size_limit_t::operator==(const size_limit_t& right) const
169 {
170 return ( (infinity==right.infinity) && (infinity || (size==right.size)) );
171 }
172
173 bool size_limit_t::is_adjacent(const size_limit_t& other) const
174 {
175 return ( !infinity && !other.infinity && (size+1==other.size) );
176 }
177
178 size_t size_limit_t::get_size() const
179 {
180 if (infinity) FATAL_ERROR("size_limit_t::get_size()");
181 return size;
182 }
183
184 size_limit_t size_limit_t::next() const
185 {
186 return ( infinity ? *this : size_limit_t(size+1) );
187 }
188
189 size_limit_t size_limit_t::previous() const
190 {
191 if (size==0) FATAL_ERROR("size_limit_t::previous()");
192 return ( infinity ? *this : size_limit_t(size-1) );
193 }
194
195 void size_limit_t::check_single_value() const
196 {
197 if (infinity) FATAL_ERROR("size_limit_t::check_single_value()");
198 }
199
200 void size_limit_t::check_interval_start() const
201 {
202 if (infinity) FATAL_ERROR("size_limit_t::check_interval_start()");
203 }
204
205 string size_limit_t::to_string() const
206 {
207 if (infinity) return string("infinity");
208 return Int2string((Int)size);
209 }
210
211 int_limit_t size_limit_t::to_int_limit() const
212 {
213 if (infinity) return int_limit_t(int_limit_t::PLUS_INFINITY);
214 return int_limit_t(int_val_t((Int)size)); // FIXME: size_t -> Int
215 }
216
217 ////////////////////////////////////////////////////////////////////////////////
218
219 const short int char_limit_t::max_char = 127;
220
221 const char_limit_t char_limit_t::minimum(0);
222
223 const char_limit_t char_limit_t::maximum(max_char);
224
225 bool char_limit_t::is_valid_value(short int p_chr)
226 {
227 return ( (p_chr>=0) && (p_chr<=max_char) );
228 }
229
230 char_limit_t::char_limit_t(short int p_chr): chr(p_chr)
231 {
232 if ( (chr<0) || (chr>max_char) ) FATAL_ERROR("char_limit_t::char_limit_t()");
233 }
234
235 char_limit_t char_limit_t::next() const
236 {
237 if (chr>=max_char) FATAL_ERROR("char_limit_t::next()");
238 return char_limit_t(chr+1);
239 }
240
241 char_limit_t char_limit_t::previous() const
242 {
243 if (chr<=0) FATAL_ERROR("char_limit_t::previous()");
244 return char_limit_t(chr-1);
245 }
246
247 string char_limit_t::to_string() const
248 {
249 return string((char)chr).get_stringRepr();
250 }
251
252 ////////////////////////////////////////////////////////////////////////////////
253
254 void universal_char_limit_t::check_value() const
255 {
256 if (code_point>max_code_point) FATAL_ERROR("universal_char_limit_t::check_value()");
257 }
258
259 unsigned int universal_char_limit_t::uchar2codepoint(const ustring::universal_char& uchr)
260 {
261 return ( (((unsigned int)uchr.group)<<24) + (((unsigned int)uchr.plane)<<16) + (((unsigned int)uchr.row)<<8) + ((unsigned int)uchr.cell) );
262 }
263
264 ustring::universal_char universal_char_limit_t::codepoint2uchar(unsigned int cp)
265 {
266 ustring::universal_char uchr;
267 uchr.cell = (unsigned char)(cp & 0xFF);
268 uchr.row = (unsigned char)((cp>>8) & 0xFF);
269 uchr.plane = (unsigned char)((cp>>16) & 0xFF);
270 uchr.group = (unsigned char)((cp>>24) & 0xFF);
271 return uchr;
272 }
273
274 const unsigned int universal_char_limit_t::max_code_point = 0x7FFFFFFF;
275
276 const universal_char_limit_t universal_char_limit_t::minimum(0);
277
278 const universal_char_limit_t universal_char_limit_t::maximum(max_code_point);
279
280 bool universal_char_limit_t::is_valid_value(const ustring::universal_char& p_uchr)
281 {
282 return (uchar2codepoint(p_uchr)<=max_code_point);
283 }
284
285 universal_char_limit_t universal_char_limit_t::next() const
286 {
287 if (code_point>=max_code_point) FATAL_ERROR("universal_char_limit_t::next()");
288 return universal_char_limit_t(code_point+1);
289 }
290
291 universal_char_limit_t universal_char_limit_t::previous() const
292 {
293 if (code_point<=0) FATAL_ERROR("universal_char_limit_t::previous()");
294 return universal_char_limit_t(code_point-1);
295 }
296
297 string universal_char_limit_t::to_string() const
298 {
299 ustring::universal_char uc = codepoint2uchar(code_point);
300 return ustring(1,&uc).get_stringRepr();
301 }
302
303 ////////////////////////////////////////////////////////////////////////////////
304
305 const real_limit_t real_limit_t::minimum(make_ttcn3float(-REAL_INFINITY));
306
307 const real_limit_t real_limit_t::maximum(make_ttcn3float(REAL_INFINITY));
308
309 void real_limit_t::check_value() const
310 {
311 if (value!=value) FATAL_ERROR("real_limit_t::check_value(): cannot be NaN");
312 if ( (value==-REAL_INFINITY) && (type==LOWER) ) FATAL_ERROR("real_limit_t::check_value(): cannot be -infinity.lower");
313 if ( (value==REAL_INFINITY) && (type==UPPER) ) FATAL_ERROR("real_limit_t::check_value(): cannot be infinity.upper");
314 }
315
316 bool real_limit_t::operator<(const real_limit_t& right) const
317 {
318 ttcn3float v1,v2;
319 v1 = value;
320 v2 = right.value;
321 return ( (v1<v2) || ((v1==v2)&&(type<right.type)) );
322 }
323
324 bool real_limit_t::operator==(const real_limit_t& right) const
325 {
326 ttcn3float v1,v2;
327 v1 = value;
328 v2 = right.value;
329 return ( (v1==v2) && (type==right.type) );
330 }
331
332 bool real_limit_t::is_adjacent(const real_limit_t& other) const
333 {
334 ttcn3float v1,v2;
335 v1 = value;
336 v2 = other.value;
337 return ( (v1==v2) && (((type==LOWER)&&(other.type==EXACT)) || ((type==EXACT)&&(other.type==UPPER))) );
338 }
339
340 real_limit_t real_limit_t::next() const
341 {
342 switch (type) {
343 case LOWER:
344 return real_limit_t(value);
345 case EXACT:
346 case UPPER:
347 return real_limit_t(value, UPPER);
348 default:
349 FATAL_ERROR("real_limit_t::next()");
350 }
351 }
352
353 real_limit_t real_limit_t::previous() const
354 {
355 switch (type) {
356 case LOWER:
357 case EXACT:
358 return real_limit_t(value, LOWER);
359 case UPPER:
360 return real_limit_t(value);
361 default:
362 FATAL_ERROR("real_limit_t::previous()");
363 }
364 }
365
366 void real_limit_t::check_single_value() const
367 {
368 if (type!=EXACT) FATAL_ERROR("real_limit_t::check_single_value()");
369 }
370
371 void real_limit_t::check_interval_start() const
372 {
373 if (type==LOWER) FATAL_ERROR("real_limit_t::check_interval_start()");
374 }
375
376 void real_limit_t::check_interval_end() const
377 {
378 if (type==UPPER) FATAL_ERROR("real_limit_t::check_interval_end()");
379 }
380
381 string real_limit_t::to_string() const
382 {
383 string ret_val;
384 if (type!=EXACT) ret_val += '!';
385 ret_val += Real2string(value);
386 return ret_val;
387 }
388
389 ////////////////////////////////////////////////////////////////////////////////
390
391 bool convert_int_to_size(const RangeListConstraint<int_limit_t>& int_range, RangeListConstraint<size_limit_t>& size_range)
392 {
393 size_range = RangeListConstraint<size_limit_t>();
394 size_range.intervals = int_range.intervals;
395 size_range.values = dynamic_array<size_limit_t>(int_range.values.size());
396 for (size_t i=0; i<int_range.values.size(); i++) {
397 const int_limit_t& il = int_range.values[i];
398 size_limit_t sl;
399 switch (il.get_type()) {
400 case int_limit_t::MINUS_INFINITY:
401 size_range = RangeListConstraint<size_limit_t>(size_limit_t::minimum, size_limit_t::maximum);
402 return false;
403 case int_limit_t::NUMBER: {
404 int_val_t number = il.get_value();
405 if ((number<0) || !number.is_native_fit()) {
406 size_range = RangeListConstraint<size_limit_t>(size_limit_t::minimum, size_limit_t::maximum);
407 return false;
408 }
409 sl = size_limit_t((size_t)number.get_val());
410 } break;
411 case int_limit_t::PLUS_INFINITY:
412 sl = size_limit_t::maximum;
413 break;
414 default:
415 FATAL_ERROR("RangeListConstraint::convert_int_to_size()");
416 }
417 size_range.values.add(sl);
418 }
419 return true;
420 }
421
422 ////////////////////////////////////////////////////////////////////////////////
423
424 bool RealRangeListConstraint::is_element(const ttcn3float& r) const
425 {
426 if (r!=r) // this is a NaN value
427 return has_nan;
428 else
429 return rlc.is_element(real_limit_t(r));
430 }
431
432 RealRangeListConstraint RealRangeListConstraint::set_operation(const RealRangeListConstraint& other, bool is_union) const
433 {
434 RealRangeListConstraint ret_val;
435 ret_val.rlc = rlc.set_operation(other.rlc, is_union);
436 ret_val.has_nan = is_union ? (has_nan || other.has_nan) : (has_nan && other.has_nan);
437 return ret_val;
438 }
439
440 RealRangeListConstraint RealRangeListConstraint::operator~() const
441 {
442 RealRangeListConstraint ret_val;
443 ret_val.rlc = ~rlc;
444 ret_val.has_nan = !has_nan;
445 return ret_val;
446 }
447
448 string RealRangeListConstraint::to_string() const
449 {
450 string ret_val;
451 ret_val += '(';
452 ret_val += rlc.to_string(false);
453 if (has_nan) {
454 if (rlc.is_empty()!=TTRUE) ret_val += ',';
455 ret_val += "NaN";
456 }
457 ret_val += ')';
458 return ret_val;
459 }
460
461 bool RealRangeListConstraint::is_upper_limit_infinity () const
462 {
463 return rlc.is_upper_limit_infinity();
464 }
465
466 bool RealRangeListConstraint::is_lower_limit_infinity () const
467 {
468 return rlc.is_lower_limit_infinity();
469 }
470
471 ////////////////////////////////////////////////////////////////////////////////
472
473 string BooleanListConstraint::to_string() const
474 {
475 string ret_val;
476 ret_val += '(';
477 if (values&BC_FALSE) ret_val += "false";
478 if (values==BC_ALL) ret_val += ',';
479 if (values&BC_TRUE) ret_val += "true";
480 ret_val += ')';
481 return ret_val;
482 }
483
484 ////////////////////////////////////////////////////////////////////////////////
485
486 string VerdicttypeListConstraint::to_string() const
487 {
488 static const size_t verdict_count = 5;
489 static const char* verdict_names[verdict_count] = { "none", "pass", "inconc", "fail", "error" };
490 string ret_val;
491 ret_val += '(';
492 bool has_value = false;
493 for (size_t i=VC_NONE,idx=0; (i<VC_ALL)&&(idx<verdict_count); i<<=1,idx++)
494 {
495 if (values&i) {
496 if (has_value) ret_val += ',';
497 ret_val += verdict_names[idx];
498 has_value = true;
499 }
500 }
501 ret_val += ')';
502 return ret_val;
503 }
504
505 ////////////////////////////////////////////////////////////////////////////////
506
507 tribool StringPatternConstraint::match(const string& str) const
508 {
509 string patt = pattern->get_full_str();
510 if (patt.size()==0) return TRIBOOL(str.size()==0);
511 string *result = regexp(str, string('(')+patt+string(')'), 0);
512 bool rv = (result->size()!=0);
513 delete result;
514 return TRIBOOL(rv);
515 }
516
517 string StringPatternConstraint::to_string() const
518 {
519 string ret_val;
520 ret_val += "pattern(";
521 ret_val += pattern->get_full_str();
522 ret_val += ')';
523 return ret_val;
524 }
525
526 ////////////////////////////////////////////////////////////////////////////////
527 // constraint classes for structured types
528
529 void ValueList::clean_up()
530 {
531 values.clear();
532 }
533
534 void ValueList::copy_content(const ValueList& other)
535 {
536 for (size_t j=0; j<other.values.size(); j++) values.add(other.values[j]);
537 }
538
539 tribool ValueList::is_equal(const ValueList& other) const
540 {
541 if (values.size()!=other.values.size()) return TFALSE;
542 dynamic_array<bool> found(other.values.size()); // helper to skip unnecessary comparisons
543 for (size_t j=0; j<other.values.size(); j++) found[j] = false;
544 for (size_t i=0; i<values.size(); i++) {
545 bool found_i = false;
546 for (size_t j=0; j<other.values.size(); j++) {
547 if (found[j]) continue; // skip already found equal elements
548 if ( (values[i]==other.values[j]) || (*(values[i])==*(other.values[j])) ) {
549 found[j] = true;
550 found_i = true;
551 break;
552 }
553 }
554 if (!found_i) return TFALSE;
555 }
556 return TTRUE;
557 }
558
559 bool ValueList::is_element(Value* v) const
560 {
561 for (size_t i=0; i<values.size(); i++) {
562 if ( (values[i]==v) || (*(values[i])==*v) ) return true;
563 }
564 return false;
565 }
566
567 ValueList ValueList::set_operation(const ValueList& other, bool is_union) const
568 {
569 ValueList ret_val;
570 if (is_union) {
571 for (size_t i=0; i<values.size(); i++) ret_val.values.add(values[i]);
572 for (size_t i=0; i<other.values.size(); i++) {
573 if (!is_element(other.values[i])) ret_val.values.add(other.values[i]);
574 }
575 } else {
576 for (size_t i=0; i<values.size(); i++) {
577 if (other.is_element(values[i])) ret_val.values.add(values[i]);
578 }
579 }
580 return ret_val;
581 }
582
583 ValueList ValueList::operator-(const ValueList& other) const
584 {
585 ValueList ret_val;
586 for (size_t i=0; i<values.size(); i++) {
587 if (!other.is_element(values[i])) ret_val.values.add(values[i]);
588 }
589 return ret_val;
590 }
591
592 void ValueList::remove(const SizeRangeListConstraint& size_constraint, bool if_element)
593 {
594 for (size_t i=0; i<values.size(); i++) {
595 if (size_constraint.is_element(size_limit_t(values[i]->get_nof_comps()))==if_element) {
596 values.replace(i,1);
597 i--;
598 }
599 }
600 }
601
602 string ValueList::to_string() const
603 {
604 string ret_val;
605 ret_val += '(';
606 for (size_t i=0; i<values.size(); i++) {
607 if (i>0) ret_val += ',';
608 ret_val += values[i]->create_stringRepr();
609 }
610 ret_val += ')';
611 return ret_val;
612 }
613
614 ////////////////////////////////////////////////////////////////////////////////
615
616 tribool ValueListConstraint::is_empty() const
617 {
618 return complemented ? values.is_full() : values.is_empty();
619 }
620
621
622 tribool ValueListConstraint::is_full() const
623 {
624 return complemented ? values.is_empty() : values.is_full();
625 }
626
627
628 tribool ValueListConstraint::is_equal(const ValueListConstraint& other) const
629 {
630 return (complemented==other.complemented) ? values.is_equal(other.values) : TUNKNOWN;
631 }
632
633
634 bool ValueListConstraint::is_element(Value* v) const
635 {
636 return complemented ^ values.is_element(v);
637 }
638
639 ValueListConstraint ValueListConstraint::operator+(const ValueListConstraint& other) const
640 {
641 ValueListConstraint ret_val;
642 if (complemented) {
643 if (other.complemented) {
644 ret_val.complemented = true;
645 ret_val.values = values * other.values;
646 } else {
647 ret_val.complemented = true;
648 ret_val.values = values - other.values;
649 }
650 } else {
651 if (other.complemented) {
652 ret_val.complemented = true;
653 ret_val.values = other.values - values;
654 } else {
655 ret_val.complemented = false;
656 ret_val.values = values + other.values;
657 }
658 }
659 return ret_val;
660 }
661
662 ValueListConstraint ValueListConstraint::operator*(const ValueListConstraint& other) const
663 {
664 ValueListConstraint ret_val;
665 if (complemented) {
666 if (other.complemented) {
667 ret_val.complemented = true;
668 ret_val.values = values + other.values;
669 } else {
670 ret_val.complemented = false;
671 ret_val.values = other.values - values;
672 }
673 } else {
674 if (other.complemented) {
675 ret_val.complemented = false;
676 ret_val.values = values - other.values;
677 } else {
678 ret_val.complemented = false;
679 ret_val.values = values * other.values;
680 }
681 }
682 return ret_val;
683 }
684
685 ValueListConstraint ValueListConstraint::operator~() const
686 {
687 ValueListConstraint ret_val;
688 ret_val.complemented = !complemented;
689 ret_val.values = values;
690 return ret_val;
691 }
692
693 string ValueListConstraint::to_string() const
694 {
695 if (complemented) {
696 string ret_val;
697 ret_val += "(ALL except ";
698 ret_val += values.to_string();
699 ret_val += ')';
700 return ret_val;
701 }
702 return values.to_string();
703 }
704
705 ////////////////////////////////////////////////////////////////////////////////
706
707 tribool RecofConstraint::is_empty() const
708 {
709 if ( (size_constraint.is_empty()==TTRUE) && (has_values.is_empty()==TTRUE) ) return TTRUE;
710 if (has_values.is_empty()==TFALSE) return TFALSE;
711 if (not_values.is_empty()==TTRUE) return TFALSE;
712 return TUNKNOWN; // the set of not_values may possibly cancel the size constraint set
713 }
714
715 tribool RecofConstraint::is_full() const
716 {
717 if ( (size_constraint.is_full()==TTRUE) && (not_values.is_empty()==TTRUE) ) return TTRUE;
718 if (not_values.is_empty()==TFALSE) return TFALSE;
719 return TUNKNOWN;
720 }
721
722 tribool RecofConstraint::is_equal(const RecofConstraint& other) const
723 {
724 if ( (size_constraint.is_equal(other.size_constraint)==TTRUE) &&
725 (has_values.is_equal(other.has_values)==TTRUE) && (not_values.is_equal(other.not_values)==TTRUE) )
726 return TTRUE;
727 return TUNKNOWN; // unknown because there's no canonical form
728 }
729
730 bool RecofConstraint::is_element(Value* v) const
731 {
732 if (size_constraint.is_element(size_limit_t(v->get_nof_comps()))) return !not_values.is_element(v);
733 return has_values.is_element(v);
734 }
735
736 // representation of two sets: [Si+Vi-Ni] where Si=size_constraint, Vi=has_values, Ni=not_values
737 // UNION: [S1+V1-N1] + [S2+V2-N2] = ... = [(S1+S2)+(V1+V2)-((~S1*N2)+(N1*~S2)+(N1*N2))]
738 // INTERSECTION: [S1+V1-N1] * [S2+V2-N2] = ... = [(S1*S2)+((S1*V2-N1)+(S2*V1-N2)+(V1*V2))-(N1+N2)]
739 RecofConstraint RecofConstraint::set_operation(const RecofConstraint& other, bool is_union) const
740 {
741 RecofConstraint ret_val;
742 ret_val.size_constraint = size_constraint.set_operation(other.size_constraint, is_union);
743 if (is_union) {
744 // V1+V2
745 ret_val.has_values = has_values + other.has_values;
746 // ~S1*N2
747 ValueList vlc1 = other.not_values;
748 vlc1.remove(size_constraint, true);
749 // N1*~S2
750 ValueList vlc2 = not_values;
751 vlc2.remove(other.size_constraint, true);
752 // ((~S1*N2)+(N1*~S2)+(N1*N2))
753 ret_val.not_values = vlc1 + vlc2 + (not_values * other.not_values);
754 } else { // intersection
755 // S2*V1-N2
756 ValueList vlc1 = has_values;
757 vlc1.remove(other.size_constraint, false);
758 vlc1 = vlc1 - other.not_values;
759 // S1*V2-N1
760 ValueList vlc2 = other.has_values;
761 vlc2.remove(size_constraint, false);
762 vlc2 = vlc2 - not_values;
763 // (S1*V2-N1)+(S2*V1-N2)+(V1*V2)
764 ret_val.has_values = (has_values * other.has_values) + vlc1 + vlc2;
765 // union of not_values
766 ret_val.not_values = not_values + other.not_values;
767 }
768 // drop the intersection, holes and points cancel each other
769 ValueList vlc = ret_val.has_values * ret_val.not_values;
770 ret_val.has_values = ret_val.has_values - vlc;
771 ret_val.not_values = ret_val.not_values - vlc;
772 // drop ret_val.has_values elements that are elements of the ret_val.size_constraint set
773 ret_val.has_values.remove(ret_val.size_constraint, true);
774 // drop ret_val.not_values elements that are not elements of the ret_val.size_constraint set
775 ret_val.not_values.remove(ret_val.size_constraint, false);
776 return ret_val;
777 }
778
779 RecofConstraint RecofConstraint::operator~() const
780 {
781 RecofConstraint ret_val;
782 ret_val.size_constraint = ~size_constraint;
783 ret_val.has_values = not_values;
784 ret_val.not_values = has_values;
785 return ret_val;
786 }
787
788 tribool RecofConstraint::get_size_limit(bool is_upper, size_limit_t& limit) const
789 {
790 if (size_constraint.is_empty()==TTRUE) return TFALSE;
791 limit = is_upper ? size_constraint.get_maximal() : size_constraint.get_minimal();
792 return TTRUE;
793 }
794
795 string RecofConstraint::to_string() const
796 {
797 string ret_val;
798 if (has_values.is_empty()!=TTRUE) ret_val += has_values.to_string();
799 if (size_constraint.is_empty()!=TTRUE) {
800 if (has_values.is_empty()!=TTRUE) ret_val += " union ";
801 ret_val += "length";
802 ret_val += size_constraint.to_string();
803 }
804 // except not_values
805 if (not_values.is_empty()!=TTRUE) {
806 ret_val += " except ";
807 ret_val += not_values.to_string();
808 }
809 return ret_val;
810 }
811
812
813 } // namespace Common
This page took 0.053785 seconds and 5 git commands to generate.