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