02adf32ebf55ebb066d515fe3b57505ca3dddfd0
[deliverable/titan.core.git] / compiler2 / subtypestuff.cc
1 ///////////////////////////////////////////////////////////////////////////////
2 // Copyright (c) 2000-2014 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 ////////////////////////////////////////////////////////////////////////////////
455
456 string BooleanListConstraint::to_string() const
457 {
458 string ret_val;
459 ret_val += '(';
460 if (values&BC_FALSE) ret_val += "false";
461 if (values==BC_ALL) ret_val += ',';
462 if (values&BC_TRUE) ret_val += "true";
463 ret_val += ')';
464 return ret_val;
465 }
466
467 ////////////////////////////////////////////////////////////////////////////////
468
469 string VerdicttypeListConstraint::to_string() const
470 {
471 static const size_t verdict_count = 5;
472 static const char* verdict_names[verdict_count] = { "none", "pass", "inconc", "fail", "error" };
473 string ret_val;
474 ret_val += '(';
475 bool has_value = false;
476 for (size_t i=VC_NONE,idx=0; (i<VC_ALL)&&(idx<verdict_count); i<<=1,idx++)
477 {
478 if (values&i) {
479 if (has_value) ret_val += ',';
480 ret_val += verdict_names[idx];
481 has_value = true;
482 }
483 }
484 ret_val += ')';
485 return ret_val;
486 }
487
488 ////////////////////////////////////////////////////////////////////////////////
489
490 tribool StringPatternConstraint::match(const string& str) const
491 {
492 string patt = pattern->get_full_str();
493 if (patt.size()==0) return TRIBOOL(str.size()==0);
494 string *result = regexp(str, string('(')+patt+string(')'), 0);
495 bool rv = (result->size()!=0);
496 delete result;
497 return TRIBOOL(rv);
498 }
499
500 string StringPatternConstraint::to_string() const
501 {
502 string ret_val;
503 ret_val += "pattern(";
504 ret_val += pattern->get_full_str();
505 ret_val += ')';
506 return ret_val;
507 }
508
509 ////////////////////////////////////////////////////////////////////////////////
510 // constraint classes for structured types
511
512 void ValueList::clean_up()
513 {
514 values.clear();
515 }
516
517 void ValueList::copy_content(const ValueList& other)
518 {
519 for (size_t j=0; j<other.values.size(); j++) values.add(other.values[j]);
520 }
521
522 tribool ValueList::is_equal(const ValueList& other) const
523 {
524 if (values.size()!=other.values.size()) return TFALSE;
525 dynamic_array<bool> found(other.values.size()); // helper to skip unnecessary comparisons
526 for (size_t j=0; j<other.values.size(); j++) found[j] = false;
527 for (size_t i=0; i<values.size(); i++) {
528 bool found_i = false;
529 for (size_t j=0; j<other.values.size(); j++) {
530 if (found[j]) continue; // skip already found equal elements
531 if ( (values[i]==other.values[j]) || (*(values[i])==*(other.values[j])) ) {
532 found[j] = true;
533 found_i = true;
534 break;
535 }
536 }
537 if (!found_i) return TFALSE;
538 }
539 return TTRUE;
540 }
541
542 bool ValueList::is_element(Value* v) const
543 {
544 for (size_t i=0; i<values.size(); i++) {
545 if ( (values[i]==v) || (*(values[i])==*v) ) return true;
546 }
547 return false;
548 }
549
550 ValueList ValueList::set_operation(const ValueList& other, bool is_union) const
551 {
552 ValueList ret_val;
553 if (is_union) {
554 for (size_t i=0; i<values.size(); i++) ret_val.values.add(values[i]);
555 for (size_t i=0; i<other.values.size(); i++) {
556 if (!is_element(other.values[i])) ret_val.values.add(other.values[i]);
557 }
558 } else {
559 for (size_t i=0; i<values.size(); i++) {
560 if (other.is_element(values[i])) ret_val.values.add(values[i]);
561 }
562 }
563 return ret_val;
564 }
565
566 ValueList ValueList::operator-(const ValueList& other) const
567 {
568 ValueList ret_val;
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 return ret_val;
573 }
574
575 void ValueList::remove(const SizeRangeListConstraint& size_constraint, bool if_element)
576 {
577 for (size_t i=0; i<values.size(); i++) {
578 if (size_constraint.is_element(size_limit_t(values[i]->get_nof_comps()))==if_element) {
579 values.replace(i,1);
580 i--;
581 }
582 }
583 }
584
585 string ValueList::to_string() const
586 {
587 string ret_val;
588 ret_val += '(';
589 for (size_t i=0; i<values.size(); i++) {
590 if (i>0) ret_val += ',';
591 ret_val += values[i]->create_stringRepr();
592 }
593 ret_val += ')';
594 return ret_val;
595 }
596
597 ////////////////////////////////////////////////////////////////////////////////
598
599 tribool ValueListConstraint::is_empty() const
600 {
601 return complemented ? values.is_full() : values.is_empty();
602 }
603
604
605 tribool ValueListConstraint::is_full() const
606 {
607 return complemented ? values.is_empty() : values.is_full();
608 }
609
610
611 tribool ValueListConstraint::is_equal(const ValueListConstraint& other) const
612 {
613 return (complemented==other.complemented) ? values.is_equal(other.values) : TUNKNOWN;
614 }
615
616
617 bool ValueListConstraint::is_element(Value* v) const
618 {
619 return complemented ^ values.is_element(v);
620 }
621
622 ValueListConstraint ValueListConstraint::operator+(const ValueListConstraint& other) const
623 {
624 ValueListConstraint ret_val;
625 if (complemented) {
626 if (other.complemented) {
627 ret_val.complemented = true;
628 ret_val.values = values * other.values;
629 } else {
630 ret_val.complemented = true;
631 ret_val.values = values - other.values;
632 }
633 } else {
634 if (other.complemented) {
635 ret_val.complemented = true;
636 ret_val.values = other.values - values;
637 } else {
638 ret_val.complemented = false;
639 ret_val.values = values + other.values;
640 }
641 }
642 return ret_val;
643 }
644
645 ValueListConstraint ValueListConstraint::operator*(const ValueListConstraint& other) const
646 {
647 ValueListConstraint ret_val;
648 if (complemented) {
649 if (other.complemented) {
650 ret_val.complemented = true;
651 ret_val.values = values + other.values;
652 } else {
653 ret_val.complemented = false;
654 ret_val.values = other.values - values;
655 }
656 } else {
657 if (other.complemented) {
658 ret_val.complemented = false;
659 ret_val.values = values - other.values;
660 } else {
661 ret_val.complemented = false;
662 ret_val.values = values * other.values;
663 }
664 }
665 return ret_val;
666 }
667
668 ValueListConstraint ValueListConstraint::operator~() const
669 {
670 ValueListConstraint ret_val;
671 ret_val.complemented = !complemented;
672 ret_val.values = values;
673 return ret_val;
674 }
675
676 string ValueListConstraint::to_string() const
677 {
678 if (complemented) {
679 string ret_val;
680 ret_val += "(ALL except ";
681 ret_val += values.to_string();
682 ret_val += ')';
683 return ret_val;
684 }
685 return values.to_string();
686 }
687
688 ////////////////////////////////////////////////////////////////////////////////
689
690 tribool RecofConstraint::is_empty() const
691 {
692 if ( (size_constraint.is_empty()==TTRUE) && (has_values.is_empty()==TTRUE) ) return TTRUE;
693 if (has_values.is_empty()==TFALSE) return TFALSE;
694 if (not_values.is_empty()==TTRUE) return TFALSE;
695 return TUNKNOWN; // the set of not_values may possibly cancel the size constraint set
696 }
697
698 tribool RecofConstraint::is_full() const
699 {
700 if ( (size_constraint.is_full()==TTRUE) && (not_values.is_empty()==TTRUE) ) return TTRUE;
701 if (not_values.is_empty()==TFALSE) return TFALSE;
702 return TUNKNOWN;
703 }
704
705 tribool RecofConstraint::is_equal(const RecofConstraint& other) const
706 {
707 if ( (size_constraint.is_equal(other.size_constraint)==TTRUE) &&
708 (has_values.is_equal(other.has_values)==TTRUE) && (not_values.is_equal(other.not_values)==TTRUE) )
709 return TTRUE;
710 return TUNKNOWN; // unknown because there's no canonical form
711 }
712
713 bool RecofConstraint::is_element(Value* v) const
714 {
715 if (size_constraint.is_element(size_limit_t(v->get_nof_comps()))) return !not_values.is_element(v);
716 return has_values.is_element(v);
717 }
718
719 // representation of two sets: [Si+Vi-Ni] where Si=size_constraint, Vi=has_values, Ni=not_values
720 // UNION: [S1+V1-N1] + [S2+V2-N2] = ... = [(S1+S2)+(V1+V2)-((~S1*N2)+(N1*~S2)+(N1*N2))]
721 // INTERSECTION: [S1+V1-N1] * [S2+V2-N2] = ... = [(S1*S2)+((S1*V2-N1)+(S2*V1-N2)+(V1*V2))-(N1+N2)]
722 RecofConstraint RecofConstraint::set_operation(const RecofConstraint& other, bool is_union) const
723 {
724 RecofConstraint ret_val;
725 ret_val.size_constraint = size_constraint.set_operation(other.size_constraint, is_union);
726 if (is_union) {
727 // V1+V2
728 ret_val.has_values = has_values + other.has_values;
729 // ~S1*N2
730 ValueList vlc1 = other.not_values;
731 vlc1.remove(size_constraint, true);
732 // N1*~S2
733 ValueList vlc2 = not_values;
734 vlc2.remove(other.size_constraint, true);
735 // ((~S1*N2)+(N1*~S2)+(N1*N2))
736 ret_val.not_values = vlc1 + vlc2 + (not_values * other.not_values);
737 } else { // intersection
738 // S2*V1-N2
739 ValueList vlc1 = has_values;
740 vlc1.remove(other.size_constraint, false);
741 vlc1 = vlc1 - other.not_values;
742 // S1*V2-N1
743 ValueList vlc2 = other.has_values;
744 vlc2.remove(size_constraint, false);
745 vlc2 = vlc2 - not_values;
746 // (S1*V2-N1)+(S2*V1-N2)+(V1*V2)
747 ret_val.has_values = (has_values * other.has_values) + vlc1 + vlc2;
748 // union of not_values
749 ret_val.not_values = not_values + other.not_values;
750 }
751 // drop the intersection, holes and points cancel each other
752 ValueList vlc = ret_val.has_values * ret_val.not_values;
753 ret_val.has_values = ret_val.has_values - vlc;
754 ret_val.not_values = ret_val.not_values - vlc;
755 // drop ret_val.has_values elements that are elements of the ret_val.size_constraint set
756 ret_val.has_values.remove(ret_val.size_constraint, true);
757 // drop ret_val.not_values elements that are not elements of the ret_val.size_constraint set
758 ret_val.not_values.remove(ret_val.size_constraint, false);
759 return ret_val;
760 }
761
762 RecofConstraint RecofConstraint::operator~() const
763 {
764 RecofConstraint ret_val;
765 ret_val.size_constraint = ~size_constraint;
766 ret_val.has_values = not_values;
767 ret_val.not_values = has_values;
768 return ret_val;
769 }
770
771 tribool RecofConstraint::get_size_limit(bool is_upper, size_limit_t& limit) const
772 {
773 if (size_constraint.is_empty()==TTRUE) return TFALSE;
774 limit = is_upper ? size_constraint.get_maximal() : size_constraint.get_minimal();
775 return TTRUE;
776 }
777
778 string RecofConstraint::to_string() const
779 {
780 string ret_val;
781 if (has_values.is_empty()!=TTRUE) ret_val += has_values.to_string();
782 if (size_constraint.is_empty()!=TTRUE) {
783 if (has_values.is_empty()!=TTRUE) ret_val += " union ";
784 ret_val += "length";
785 ret_val += size_constraint.to_string();
786 }
787 // except not_values
788 if (not_values.is_empty()!=TTRUE) {
789 ret_val += " except ";
790 ret_val += not_values.to_string();
791 }
792 return ret_val;
793 }
794
795
796 } // namespace Common
This page took 0.048278 seconds and 5 git commands to generate.