1 /* Interval boundary functions.
2 Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it>
3 Copyright (C) 2010-2016 BUGSENG srl (http://bugseng.com)
4
5 This file is part of the Parma Polyhedra Library (PPL).
6
7 The PPL is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11
12 The PPL is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
20
21 For the most up-to-date information see the Parma Polyhedra Library
22 site: http://bugseng.com/products/ppl/ . */
23
24 #ifndef PPL_Boundary_defs_hh
25 #define PPL_Boundary_defs_hh 1
26
27 #include "Checked_Number_defs.hh"
28
29 namespace Parma_Polyhedra_Library {
30
31 namespace Boundary_NS {
32
33 struct Property {
34 enum Type {
35 SPECIAL_,
36 OPEN_
37 };
38 typedef bool Value;
39 static const Value default_value = true;
40 static const Value unsupported_value = false;
PropertyParma_Polyhedra_Library::Boundary_NS::Property41 Property(Type t)
42 : type(t) {
43 }
44 Type type;
45 };
46
47 static const Property SPECIAL(Property::SPECIAL_);
48 static const Property OPEN(Property::OPEN_);
49
50 enum Boundary_Type {
51 LOWER = ROUND_DOWN,
52 UPPER = ROUND_UP
53 };
54
55 inline Rounding_Dir
round_dir_check(Boundary_Type t,bool check=false)56 round_dir_check(Boundary_Type t, bool check = false) {
57 if (check) {
58 return static_cast<Rounding_Dir>(t) | ROUND_STRICT_RELATION;
59 }
60 else {
61 return static_cast<Rounding_Dir>(t);
62 }
63 }
64
65 template <typename T, typename Info>
66 inline Result
special_set_boundary_infinity(Boundary_Type type,T &,Info & info)67 special_set_boundary_infinity(Boundary_Type type, T&, Info& info) {
68 PPL_ASSERT(Info::store_special);
69 info.set_boundary_property(type, SPECIAL);
70 return V_EQ;
71 }
72
73 template <typename T, typename Info>
74 inline bool
special_is_open(Boundary_Type,const T &,const Info &)75 special_is_open(Boundary_Type, const T&, const Info&) {
76 return !Info::may_contain_infinity;
77 }
78
79 template <typename T, typename Info>
80 inline bool
normal_is_open(Boundary_Type type,const T & x,const Info & info)81 normal_is_open(Boundary_Type type, const T& x, const Info& info) {
82 if (Info::store_open) {
83 return info.get_boundary_property(type, OPEN);
84 }
85 else {
86 return !Info::store_special && !Info::may_contain_infinity
87 && normal_is_boundary_infinity(type, x, info);
88 }
89 }
90
91 template <typename T, typename Info>
92 inline bool
is_open(Boundary_Type type,const T & x,const Info & info)93 is_open(Boundary_Type type, const T& x, const Info& info) {
94 if (Info::store_open) {
95 return info.get_boundary_property(type, OPEN);
96 }
97 else {
98 return !Info::may_contain_infinity
99 && is_boundary_infinity(type, x, info);
100 }
101 }
102
103 template <typename T, typename Info>
104 inline Result
set_unbounded(Boundary_Type type,T & x,Info & info)105 set_unbounded(Boundary_Type type, T& x, Info& info) {
106 PPL_COMPILE_TIME_CHECK(Info::store_special
107 || std::numeric_limits<T>::is_bounded
108 || std::numeric_limits<T>::has_infinity,
109 "unbounded is not representable");
110 Result r;
111 if (Info::store_special) {
112 r = special_set_boundary_infinity(type, x, info);
113 }
114 else if (type == LOWER) {
115 r = assign_r(x, MINUS_INFINITY, ROUND_UP);
116 }
117 else {
118 r = assign_r(x, PLUS_INFINITY, ROUND_DOWN);
119 }
120 if (result_relation(r) == VR_EQ && !Info::may_contain_infinity) {
121 info.set_boundary_property(type, OPEN);
122 }
123 return r;
124 }
125
126 template <typename T, typename Info>
127 inline Result
set_minus_infinity(Boundary_Type type,T & x,Info & info,bool open=false)128 set_minus_infinity(Boundary_Type type, T& x, Info& info, bool open = false) {
129 if (open) {
130 PPL_ASSERT(type == LOWER);
131 }
132 else {
133 PPL_ASSERT(Info::may_contain_infinity);
134 }
135 Result r;
136 if (Info::store_special) {
137 PPL_ASSERT(type == LOWER);
138 r = special_set_boundary_infinity(type, x, info);
139 }
140 else {
141 r = assign_r(x, MINUS_INFINITY, round_dir_check(type));
142 PPL_ASSERT(result_representable(r));
143 }
144 if (open || result_relation(r) != VR_EQ) {
145 info.set_boundary_property(type, OPEN);
146 }
147 return r;
148 }
149
150 template <typename T, typename Info>
151 inline Result
set_plus_infinity(Boundary_Type type,T & x,Info & info,bool open=false)152 set_plus_infinity(Boundary_Type type, T& x, Info& info, bool open = false) {
153 if (open) {
154 PPL_ASSERT(type == UPPER);
155 }
156 else {
157 PPL_ASSERT(Info::may_contain_infinity);
158 }
159 Result r;
160 if (Info::store_special) {
161 PPL_ASSERT(type == UPPER);
162 r = special_set_boundary_infinity(type, x, info);
163 }
164 else {
165 r = assign_r(x, PLUS_INFINITY, round_dir_check(type));
166 PPL_ASSERT(result_representable(r));
167 }
168 if (open || result_relation(r) != VR_EQ) {
169 info.set_boundary_property(type, OPEN);
170 }
171 return r;
172 }
173
174 template <typename T, typename Info>
175 inline Result
set_boundary_infinity(Boundary_Type type,T & x,Info & info,bool open=false)176 set_boundary_infinity(Boundary_Type type, T& x, Info& info, bool open = false) {
177 PPL_ASSERT(open || Info::may_contain_infinity);
178 Result r;
179 if (Info::store_special) {
180 r = special_set_boundary_infinity(type, x, info);
181 }
182 else if (type == LOWER) {
183 r = assign_r(x, MINUS_INFINITY, round_dir_check(type));
184 }
185 else {
186 r = assign_r(x, PLUS_INFINITY, round_dir_check(type));
187 }
188 PPL_ASSERT(result_representable(r));
189 if (open) {
190 info.set_boundary_property(type, OPEN);
191 }
192 return r;
193 }
194
195 template <typename T, typename Info>
196 inline bool
is_domain_inf(Boundary_Type type,const T & x,const Info & info)197 is_domain_inf(Boundary_Type type, const T& x, const Info& info) {
198 if (Info::store_special && type == LOWER) {
199 return info.get_boundary_property(type, SPECIAL);
200 }
201 else if (std::numeric_limits<T>::has_infinity) {
202 return Parma_Polyhedra_Library::is_minus_infinity(x);
203 }
204 else if (std::numeric_limits<T>::is_bounded) {
205 return x == std::numeric_limits<T>::min();
206 }
207 else {
208 return false;
209 }
210 }
211
212 template <typename T, typename Info>
213 inline bool
is_domain_sup(Boundary_Type type,const T & x,const Info & info)214 is_domain_sup(Boundary_Type type, const T& x, const Info& info) {
215 if (Info::store_special && type == UPPER) {
216 return info.get_boundary_property(type, SPECIAL);
217 }
218 else if (std::numeric_limits<T>::has_infinity) {
219 return Parma_Polyhedra_Library::is_plus_infinity(x);
220 }
221 else if (std::numeric_limits<T>::is_bounded) {
222 return x == std::numeric_limits<T>::max();
223 }
224 else {
225 return false;
226 }
227 }
228
229 template <typename T, typename Info>
230 inline bool
normal_is_boundary_infinity(Boundary_Type type,const T & x,const Info &)231 normal_is_boundary_infinity(Boundary_Type type, const T& x, const Info&) {
232 if (!std::numeric_limits<T>::has_infinity) {
233 return false;
234 }
235 if (type == LOWER) {
236 return Parma_Polyhedra_Library::is_minus_infinity(x);
237 }
238 else {
239 return Parma_Polyhedra_Library::is_plus_infinity(x);
240 }
241 }
242
243 template <typename T, typename Info>
244 inline bool
is_boundary_infinity(Boundary_Type type,const T & x,const Info & info)245 is_boundary_infinity(Boundary_Type type, const T& x, const Info& info) {
246 if (Info::store_special) {
247 return info.get_boundary_property(type, SPECIAL);
248 }
249 else {
250 return normal_is_boundary_infinity(type, x, info);
251 }
252 }
253
254 template <typename T, typename Info>
255 inline bool
normal_is_reverse_infinity(Boundary_Type type,const T & x,const Info &)256 normal_is_reverse_infinity(Boundary_Type type, const T& x, const Info&) {
257 if (!Info::may_contain_infinity) {
258 return false;
259 }
260 else if (type == LOWER) {
261 return Parma_Polyhedra_Library::is_plus_infinity(x);
262 }
263 else {
264 return Parma_Polyhedra_Library::is_minus_infinity(x);
265 }
266 }
267
268 template <typename T, typename Info>
269 inline bool
is_minus_infinity(Boundary_Type type,const T & x,const Info & info)270 is_minus_infinity(Boundary_Type type, const T& x, const Info& info) {
271 if (type == LOWER) {
272 if (Info::store_special) {
273 return info.get_boundary_property(type, SPECIAL);
274 }
275 else {
276 return normal_is_boundary_infinity(type, x, info);
277 }
278 }
279 else {
280 return !Info::store_special && normal_is_reverse_infinity(type, x, info);
281 }
282 }
283
284 template <typename T, typename Info>
285 inline bool
is_plus_infinity(Boundary_Type type,const T & x,const Info & info)286 is_plus_infinity(Boundary_Type type, const T& x, const Info& info) {
287 if (type == UPPER) {
288 if (Info::store_special) {
289 return info.get_boundary_property(type, SPECIAL);
290 }
291 else {
292 return normal_is_boundary_infinity(type, x, info);
293 }
294 }
295 else {
296 return !Info::store_special && normal_is_reverse_infinity(type, x, info);
297 }
298 }
299
300 template <typename T, typename Info>
301 inline bool
is_reverse_infinity(Boundary_Type type,const T & x,const Info & info)302 is_reverse_infinity(Boundary_Type type, const T& x, const Info& info) {
303 return normal_is_reverse_infinity(type, x, info);
304 }
305
306 template <typename T, typename Info>
307 inline int
infinity_sign(Boundary_Type type,const T & x,const Info & info)308 infinity_sign(Boundary_Type type, const T& x, const Info& info) {
309 if (is_boundary_infinity(type, x, info)) {
310 return (type == LOWER) ? -1 : 1;
311 }
312 else if (is_reverse_infinity(type, x, info)) {
313 return (type == UPPER) ? -1 : 1;
314 }
315 else {
316 return 0;
317 }
318 }
319
320 template <typename T, typename Info>
321 inline bool
is_boundary_infinity_closed(Boundary_Type type,const T & x,const Info & info)322 is_boundary_infinity_closed(Boundary_Type type, const T& x, const Info& info) {
323 return Info::may_contain_infinity
324 && !info.get_boundary_property(type, OPEN)
325 && is_boundary_infinity(type, x, info);
326 }
327
328 template <typename Info>
329 inline bool
boundary_infinity_is_open(Boundary_Type type,const Info & info)330 boundary_infinity_is_open(Boundary_Type type, const Info& info) {
331 return !Info::may_contain_infinity
332 || info.get_boundary_property(type, OPEN);
333 }
334
335 template <typename T, typename Info>
336 inline int
sgn_b(Boundary_Type type,const T & x,const Info & info)337 sgn_b(Boundary_Type type, const T& x, const Info& info) {
338 if (info.get_boundary_property(type, SPECIAL)) {
339 return (type == LOWER) ? -1 : 1;
340 }
341 else {
342 // The following Parma_Polyhedra_Library:: qualification is to work
343 // around a bug of GCC 4.0.x.
344 return Parma_Polyhedra_Library::sgn(x);
345 }
346 }
347
348 template <typename T, typename Info>
349 inline int
sgn(Boundary_Type type,const T & x,const Info & info)350 sgn(Boundary_Type type, const T& x, const Info& info) {
351 int sign = sgn_b(type, x, info);
352 if (x == 0 && info.get_boundary_property(type, OPEN)) {
353 return (type == LOWER) ? -1 : 1;
354 }
355 else {
356 return sign;
357 }
358 }
359
360 template <typename T1, typename Info1, typename T2, typename Info2>
361 inline bool
eq(Boundary_Type type1,const T1 & x1,const Info1 & info1,Boundary_Type type2,const T2 & x2,const Info2 & info2)362 eq(Boundary_Type type1, const T1& x1, const Info1& info1,
363 Boundary_Type type2, const T2& x2, const Info2& info2) {
364 if (type1 == type2) {
365 if (is_open(type1, x1, info1)
366 != is_open(type2, x2, info2)) {
367 return false;
368 }
369 }
370 else if (is_open(type1, x1, info1)
371 || is_open(type2, x2, info2)) {
372 return false;
373 }
374 if (is_minus_infinity(type1, x1, info1)) {
375 return is_minus_infinity(type2, x2, info2);
376 }
377 else if (is_plus_infinity(type1, x1, info1)) {
378 return is_plus_infinity(type2, x2, info2);
379 }
380 else if (is_minus_infinity(type2, x2, info2)
381 || is_plus_infinity(type2, x2, info2)) {
382 return false;
383 }
384 else {
385 return equal(x1, x2);
386 }
387 }
388
389 template <typename T1, typename Info1, typename T2, typename Info2>
390 inline bool
lt(Boundary_Type type1,const T1 & x1,const Info1 & info1,Boundary_Type type2,const T2 & x2,const Info2 & info2)391 lt(Boundary_Type type1, const T1& x1, const Info1& info1,
392 Boundary_Type type2, const T2& x2, const Info2& info2) {
393 if (is_open(type1, x1, info1)) {
394 if (type1 == UPPER
395 && (type2 == LOWER
396 || !is_open(type2, x2, info2))) {
397 goto le;
398 }
399 }
400 else if (type2 == LOWER
401 && is_open(type2, x2, info2)) {
402 le:
403 if (is_minus_infinity(type1, x1, info1)
404 || is_plus_infinity(type2, x2, info2)) {
405 return true;
406 }
407 if (is_plus_infinity(type1, x1, info1)
408 || is_minus_infinity(type2, x2, info2)) {
409 return false;
410 }
411 else {
412 return less_or_equal(x1, x2);
413 }
414 }
415 if (is_plus_infinity(type1, x1, info1)
416 || is_minus_infinity(type2, x2, info2)) {
417 return false;
418 }
419 if (is_minus_infinity(type1, x1, info1)
420 || is_plus_infinity(type2, x2, info2)) {
421 return true;
422 }
423 else {
424 return less_than(x1, x2);
425 }
426 }
427
428 template <typename T1, typename Info1, typename T2, typename Info2>
429 inline bool
gt(Boundary_Type type1,const T1 & x1,const Info1 & info1,Boundary_Type type2,const T2 & x2,const Info2 & info2)430 gt(Boundary_Type type1, const T1& x1, const Info1& info1,
431 Boundary_Type type2, const T2& x2, const Info2& info2) {
432 return lt(type2, x2, info2, type1, x1, info1);
433 }
434
435 template <typename T1, typename Info1, typename T2, typename Info2>
436 inline bool
le(Boundary_Type type1,const T1 & x1,const Info1 & info1,Boundary_Type type2,const T2 & x2,const Info2 & info2)437 le(Boundary_Type type1, const T1& x1, const Info1& info1,
438 Boundary_Type type2, const T2& x2, const Info2& info2) {
439 return !gt(type1, x1, info1, type2, x2, info2);
440 }
441
442 template <typename T1, typename Info1, typename T2, typename Info2>
443 inline bool
ge(Boundary_Type type1,const T1 & x1,const Info1 & info1,Boundary_Type type2,const T2 & x2,const Info2 & info2)444 ge(Boundary_Type type1, const T1& x1, const Info1& info1,
445 Boundary_Type type2, const T2& x2, const Info2& info2) {
446 return !lt(type1, x1, info1, type2, x2, info2);
447 }
448
449 template <typename T, typename Info>
450 inline Result
adjust_boundary(Boundary_Type type,T & x,Info & info,bool open,Result r)451 adjust_boundary(Boundary_Type type, T& x, Info& info,
452 bool open, Result r) {
453 r = result_relation_class(r);
454 if (type == LOWER) {
455 switch (r) {
456 case V_GT_MINUS_INFINITY:
457 open = true;
458 /* Fall through */
459 case V_EQ_MINUS_INFINITY:
460 if (!Info::store_special) {
461 return r;
462 }
463 if (open) {
464 info.set_boundary_property(type, OPEN);
465 }
466 return special_set_boundary_infinity(type, x, info);
467 case V_GT:
468 open = true;
469 /* Fall through */
470 case V_GE:
471 case V_EQ:
472 if (open) {
473 info.set_boundary_property(type, OPEN);
474 }
475 return r;
476 default:
477 PPL_UNREACHABLE;
478 return V_NAN;
479 }
480 }
481 else {
482 switch (r) {
483 case V_LT_PLUS_INFINITY:
484 open = true;
485 /* Fall through */
486 case V_EQ_PLUS_INFINITY:
487 if (!Info::store_special) {
488 return r;
489 }
490 if (open) {
491 info.set_boundary_property(type, OPEN);
492 }
493 return special_set_boundary_infinity(type, x, info);
494 case V_LT:
495 open = true;
496 /* Fall through */
497 case V_LE:
498 case V_EQ:
499 if (open) {
500 info.set_boundary_property(type, OPEN);
501 }
502 return r;
503 default:
504 PPL_UNREACHABLE;
505 return V_NAN;
506 }
507 }
508 }
509
510 template <typename To, typename To_Info, typename T, typename Info>
511 inline Result
complement(Boundary_Type to_type,To & to,To_Info & to_info,Boundary_Type type,const T & x,const Info & info)512 complement(Boundary_Type to_type, To& to, To_Info& to_info,
513 Boundary_Type type, const T& x, const Info& info) {
514 PPL_ASSERT(to_type != type);
515 bool should_shrink;
516 if (info.get_boundary_property(type, SPECIAL)) {
517 should_shrink = !special_is_open(type, x, info);
518 if (type == LOWER) {
519 return set_minus_infinity(to_type, to, to_info, should_shrink);
520 }
521 else {
522 return set_plus_infinity(to_type, to, to_info, should_shrink);
523 }
524 }
525 should_shrink = !normal_is_open(type, x, info);
526 bool check = (To_Info::check_inexact || (!should_shrink && To_Info::store_open));
527 Result r = assign_r(to, x, round_dir_check(to_type, check));
528 return adjust_boundary(to_type, to, to_info, should_shrink, r);
529 }
530
531 template <typename To, typename To_Info, typename T, typename Info>
532 inline Result
assign(Boundary_Type to_type,To & to,To_Info & to_info,Boundary_Type type,const T & x,const Info & info,bool should_shrink=false)533 assign(Boundary_Type to_type, To& to, To_Info& to_info,
534 Boundary_Type type, const T& x, const Info& info,
535 bool should_shrink = false) {
536 PPL_ASSERT(to_type == type);
537 if (info.get_boundary_property(type, SPECIAL)) {
538 should_shrink = (should_shrink || special_is_open(type, x, info));
539 return set_boundary_infinity(to_type, to, to_info, should_shrink);
540 }
541 should_shrink = (should_shrink || normal_is_open(type, x, info));
542 const bool check
543 = (To_Info::check_inexact || (!should_shrink && To_Info::store_open));
544 const Result r = assign_r(to, x, round_dir_check(to_type, check));
545 return adjust_boundary(to_type, to, to_info, should_shrink, r);
546 }
547
548 template <typename To, typename To_Info, typename T, typename Info>
549 inline Result
min_assign(Boundary_Type to_type,To & to,To_Info & to_info,Boundary_Type type,const T & x,const Info & info)550 min_assign(Boundary_Type to_type, To& to, To_Info& to_info,
551 Boundary_Type type, const T& x, const Info& info) {
552 if (lt(type, x, info, to_type, to, to_info)) {
553 to_info.clear_boundary_properties(to_type);
554 return assign(to_type, to, to_info, type, x, info);
555 }
556 return V_EQ;
557 }
558
559 template <typename To, typename To_Info, typename T1, typename Info1, typename T2, typename Info2>
560 inline Result
min_assign(Boundary_Type to_type,To & to,To_Info & to_info,Boundary_Type type1,const T1 & x1,const Info1 & info1,Boundary_Type type2,const T2 & x2,const Info2 & info2)561 min_assign(Boundary_Type to_type, To& to, To_Info& to_info,
562 Boundary_Type type1, const T1& x1, const Info1& info1,
563 Boundary_Type type2, const T2& x2, const Info2& info2) {
564 if (lt(type1, x1, info1, type2, x2, info2)) {
565 return assign(to_type, to, to_info, type1, x1, info1);
566 }
567 else {
568 return assign(to_type, to, to_info, type2, x2, info2);
569 }
570 }
571
572 template <typename To, typename To_Info, typename T, typename Info>
573 inline Result
max_assign(Boundary_Type to_type,To & to,To_Info & to_info,Boundary_Type type,const T & x,const Info & info)574 max_assign(Boundary_Type to_type, To& to, To_Info& to_info,
575 Boundary_Type type, const T& x, const Info& info) {
576 if (gt(type, x, info, to_type, to, to_info)) {
577 to_info.clear_boundary_properties(to_type);
578 return assign(to_type, to, to_info, type, x, info);
579 }
580 return V_EQ;
581 }
582
583 template <typename To, typename To_Info, typename T1, typename Info1, typename T2, typename Info2>
584 inline Result
max_assign(Boundary_Type to_type,To & to,To_Info & to_info,Boundary_Type type1,const T1 & x1,const Info1 & info1,Boundary_Type type2,const T2 & x2,const Info2 & info2)585 max_assign(Boundary_Type to_type, To& to, To_Info& to_info,
586 Boundary_Type type1, const T1& x1, const Info1& info1,
587 Boundary_Type type2, const T2& x2, const Info2& info2) {
588 if (gt(type1, x1, info1, type2, x2, info2)) {
589 return assign(to_type, to, to_info, type1, x1, info1);
590 }
591 else {
592 return assign(to_type, to, to_info, type2, x2, info2);
593 }
594 }
595
596 template <typename To, typename To_Info, typename T, typename Info>
597 inline Result
neg_assign(Boundary_Type to_type,To & to,To_Info & to_info,Boundary_Type type,const T & x,const Info & info)598 neg_assign(Boundary_Type to_type, To& to, To_Info& to_info,
599 Boundary_Type type, const T& x, const Info& info) {
600 PPL_ASSERT(to_type != type);
601 bool should_shrink;
602 if (info.get_boundary_property(type, SPECIAL)) {
603 should_shrink = special_is_open(type, x, info);
604 return set_boundary_infinity(to_type, to, to_info, should_shrink);
605 }
606 should_shrink = normal_is_open(type, x, info);
607 bool check = (To_Info::check_inexact || (!should_shrink && To_Info::store_open));
608 Result r = neg_assign_r(to, x, round_dir_check(to_type, check));
609 return adjust_boundary(to_type, to, to_info, should_shrink, r);
610 }
611
612 template <typename To, typename To_Info, typename T1, typename Info1, typename T2, typename Info2>
613 inline Result
add_assign(Boundary_Type to_type,To & to,To_Info & to_info,Boundary_Type type1,const T1 & x1,const Info1 & info1,Boundary_Type type2,const T2 & x2,const Info2 & info2)614 add_assign(Boundary_Type to_type, To& to, To_Info& to_info,
615 Boundary_Type type1, const T1& x1, const Info1& info1,
616 Boundary_Type type2, const T2& x2, const Info2& info2) {
617 PPL_ASSERT(type1 == type2);
618 bool should_shrink;
619 if (is_boundary_infinity(type1, x1, info1)) {
620 should_shrink = (boundary_infinity_is_open(type1, info1)
621 && !is_boundary_infinity_closed(type2, x2, info2));
622 return set_boundary_infinity(to_type, to, to_info, should_shrink);
623 }
624 else if (is_boundary_infinity(type2, x2, info2)) {
625 should_shrink = (boundary_infinity_is_open(type2, info2)
626 && !is_boundary_infinity_closed(type1, x1, info1));
627 return set_boundary_infinity(to_type, to, to_info, should_shrink);
628 }
629 should_shrink = (normal_is_open(type1, x1, info1)
630 || normal_is_open(type2, x2, info2));
631 bool check = (To_Info::check_inexact || (!should_shrink && To_Info::store_open));
632 // FIXME: extended handling is not needed
633 Result r = add_assign_r(to, x1, x2, round_dir_check(to_type, check));
634 return adjust_boundary(to_type, to, to_info, should_shrink, r);
635 }
636
637 template <typename To, typename To_Info, typename T1, typename Info1, typename T2, typename Info2>
638 inline Result
sub_assign(Boundary_Type to_type,To & to,To_Info & to_info,Boundary_Type type1,const T1 & x1,const Info1 & info1,Boundary_Type type2,const T2 & x2,const Info2 & info2)639 sub_assign(Boundary_Type to_type, To& to, To_Info& to_info,
640 Boundary_Type type1, const T1& x1, const Info1& info1,
641 Boundary_Type type2, const T2& x2, const Info2& info2) {
642 PPL_ASSERT(type1 != type2);
643 bool should_shrink;
644 if (is_boundary_infinity(type1, x1, info1)) {
645 should_shrink = (boundary_infinity_is_open(type1, info1)
646 && !is_boundary_infinity_closed(type2, x2, info2));
647 return set_boundary_infinity(to_type, to, to_info, should_shrink);
648 }
649 else if (is_boundary_infinity(type2, x2, info2)) {
650 should_shrink = (boundary_infinity_is_open(type2, info2)
651 && !is_boundary_infinity_closed(type1, x1, info1));
652 return set_boundary_infinity(to_type, to, to_info, should_shrink);
653 }
654 should_shrink = (normal_is_open(type1, x1, info1)
655 || normal_is_open(type2, x2, info2));
656 bool check = (To_Info::check_inexact || (!should_shrink && To_Info::store_open));
657 // FIXME: extended handling is not needed
658 Result r = sub_assign_r(to, x1, x2, round_dir_check(to_type, check));
659 return adjust_boundary(to_type, to, to_info, should_shrink, r);
660 }
661
662 template <typename To, typename To_Info, typename T1, typename Info1, typename T2, typename Info2>
663 inline Result
mul_assign(Boundary_Type to_type,To & to,To_Info & to_info,Boundary_Type type1,const T1 & x1,const Info1 & info1,Boundary_Type type2,const T2 & x2,const Info2 & info2)664 mul_assign(Boundary_Type to_type, To& to, To_Info& to_info,
665 Boundary_Type type1, const T1& x1, const Info1& info1,
666 Boundary_Type type2, const T2& x2, const Info2& info2) {
667 bool should_shrink;
668 if (is_boundary_infinity(type1, x1, info1)) {
669 should_shrink = (boundary_infinity_is_open(type1, info1)
670 && !is_boundary_infinity_closed(type2, x2, info2));
671 return set_boundary_infinity(to_type, to, to_info, should_shrink);
672 }
673 else if (is_boundary_infinity(type2, x2, info2)) {
674 should_shrink = (boundary_infinity_is_open(type2, info2)
675 && !is_boundary_infinity_closed(type1, x1, info1));
676 return set_boundary_infinity(to_type, to, to_info, should_shrink);
677 }
678 should_shrink = (normal_is_open(type1, x1, info1)
679 || normal_is_open(type2, x2, info2));
680 bool check = (To_Info::check_inexact || (!should_shrink && To_Info::store_open));
681 PPL_ASSERT(x1 != Constant<0>::value && x2 != Constant<0>::value);
682 // FIXME: extended handling is not needed
683 Result r = mul_assign_r(to, x1, x2, round_dir_check(to_type, check));
684 return adjust_boundary(to_type, to, to_info, should_shrink, r);
685 }
686
687 template <typename To, typename To_Info>
688 inline Result
set_zero(Boundary_Type to_type,To & to,To_Info & to_info,bool should_shrink)689 set_zero(Boundary_Type to_type, To& to, To_Info& to_info, bool should_shrink) {
690 bool check = (To_Info::check_inexact || (!should_shrink && To_Info::store_open));
691 Result r = assign_r(to, Constant<0>::value, round_dir_check(to_type, check));
692 return adjust_boundary(to_type, to, to_info, should_shrink, r);
693 }
694
695 template <typename To, typename To_Info, typename T1, typename Info1, typename T2, typename Info2>
696 inline Result
mul_assign_z(Boundary_Type to_type,To & to,To_Info & to_info,Boundary_Type type1,const T1 & x1,const Info1 & info1,int x1s,Boundary_Type type2,const T2 & x2,const Info2 & info2,int x2s)697 mul_assign_z(Boundary_Type to_type, To& to, To_Info& to_info,
698 Boundary_Type type1, const T1& x1, const Info1& info1, int x1s,
699 Boundary_Type type2, const T2& x2, const Info2& info2, int x2s) {
700 bool should_shrink;
701 if (x1s != 0) {
702 if (x2s != 0) {
703 return mul_assign(to_type, to, to_info,
704 type1, x1, info1,
705 type2, x2, info2);
706 }
707 else {
708 should_shrink = info2.get_boundary_property(type2, OPEN);
709 }
710 }
711 else {
712 should_shrink = (info1.get_boundary_property(type1, OPEN)
713 && (x2s != 0 || info2.get_boundary_property(type2, OPEN)));
714 }
715 return set_zero(to_type, to, to_info, should_shrink);
716 }
717
718 template <typename To, typename To_Info, typename T1, typename Info1, typename T2, typename Info2>
719 inline Result
div_assign(Boundary_Type to_type,To & to,To_Info & to_info,Boundary_Type type1,const T1 & x1,const Info1 & info1,Boundary_Type type2,const T2 & x2,const Info2 & info2)720 div_assign(Boundary_Type to_type, To& to, To_Info& to_info,
721 Boundary_Type type1, const T1& x1, const Info1& info1,
722 Boundary_Type type2, const T2& x2, const Info2& info2) {
723 bool should_shrink;
724 if (is_boundary_infinity(type1, x1, info1)) {
725 should_shrink = boundary_infinity_is_open(type1, info1);
726 return set_boundary_infinity(to_type, to, to_info, should_shrink);
727 }
728 else if (is_boundary_infinity(type2, x2, info2)) {
729 should_shrink = boundary_infinity_is_open(type2, info2);
730 return set_zero(to_type, to, to_info, should_shrink);
731 }
732 should_shrink = (normal_is_open(type1, x1, info1)
733 || normal_is_open(type2, x2, info2));
734 bool check = (To_Info::check_inexact || (!should_shrink && To_Info::store_open));
735 PPL_ASSERT(x1 != Constant<0>::value && x2 != Constant<0>::value);
736 // FIXME: extended handling is not needed
737 Result r = div_assign_r(to, x1, x2, round_dir_check(to_type, check));
738 return adjust_boundary(to_type, to, to_info, should_shrink, r);
739 }
740
741
742 template <typename To, typename To_Info, typename T1, typename Info1, typename T2, typename Info2>
743 inline Result
div_assign_z(Boundary_Type to_type,To & to,To_Info & to_info,Boundary_Type type1,const T1 & x1,const Info1 & info1,int x1s,Boundary_Type type2,const T2 & x2,const Info2 & info2,int x2s)744 div_assign_z(Boundary_Type to_type, To& to, To_Info& to_info,
745 Boundary_Type type1, const T1& x1, const Info1& info1, int x1s,
746 Boundary_Type type2, const T2& x2, const Info2& info2, int x2s) {
747 if (x1s != 0) {
748 if (x2s != 0) {
749 return div_assign(to_type, to, to_info,
750 type1, x1, info1,
751 type2, x2, info2);
752 }
753 else {
754 return set_boundary_infinity(to_type, to, to_info, true);
755 }
756 }
757 else {
758 bool should_shrink = info1.get_boundary_property(type1, OPEN)
759 && !is_boundary_infinity_closed(type2, x2, info2);
760 return set_zero(to_type, to, to_info, should_shrink);
761 }
762 }
763
764 template <typename To, typename To_Info, typename T, typename Info>
765 inline Result
umod_2exp_assign(Boundary_Type to_type,To & to,To_Info & to_info,Boundary_Type type,const T & x,const Info & info,unsigned int exp)766 umod_2exp_assign(Boundary_Type to_type, To& to, To_Info& to_info,
767 Boundary_Type type, const T& x, const Info& info,
768 unsigned int exp) {
769 PPL_ASSERT(to_type == type);
770 bool should_shrink;
771 if (is_boundary_infinity(type, x, info)) {
772 should_shrink = boundary_infinity_is_open(type, info);
773 return set_boundary_infinity(to_type, to, to_info, should_shrink);
774 }
775 should_shrink = normal_is_open(type, x, info);
776 bool check = (To_Info::check_inexact || (!should_shrink && To_Info::store_open));
777 Result r = umod_2exp_assign_r(to, x, exp, round_dir_check(to_type, check));
778 return adjust_boundary(to_type, to, to_info, should_shrink, r);
779 }
780
781 template <typename To, typename To_Info, typename T, typename Info>
782 inline Result
smod_2exp_assign(Boundary_Type to_type,To & to,To_Info & to_info,Boundary_Type type,const T & x,const Info & info,unsigned int exp)783 smod_2exp_assign(Boundary_Type to_type, To& to, To_Info& to_info,
784 Boundary_Type type, const T& x, const Info& info,
785 unsigned int exp) {
786 PPL_ASSERT(to_type == type);
787 bool should_shrink;
788 if (is_boundary_infinity(type, x, info)) {
789 should_shrink = boundary_infinity_is_open(type, info);
790 return set_boundary_infinity(to_type, to, to_info, should_shrink);
791 }
792 should_shrink = normal_is_open(type, x, info);
793 bool check = (To_Info::check_inexact || (!should_shrink && To_Info::store_open));
794 Result r = smod_2exp_assign_r(to, x, exp, round_dir_check(to_type, check));
795 return adjust_boundary(to_type, to, to_info, should_shrink, r);
796 }
797
798 } // namespace Boundary_NS
799
800 } // namespace Parma_Polyhedra_Library
801
802 #endif // !defined(PPL_Boundary_defs_hh)
803