PPL  1.2
Boundary_defs.hh
Go to the documentation of this file.
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 {
37  };
38  typedef bool Value;
39  static const Value default_value = true;
40  static const Value unsupported_value = false;
42  : type(t) {
43  }
45 };
46 
47 static const Property SPECIAL(Property::SPECIAL_);
48 static const Property OPEN(Property::OPEN_);
49 
53 };
54 
55 inline Rounding_Dir
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
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
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
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
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
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) {
116  }
117  else {
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
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
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
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
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) {
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
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) {
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
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) {
237  }
238  else {
240  }
241 }
242 
243 template <typename T, typename Info>
244 inline bool
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
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) {
262  }
263  else {
265  }
266 }
267 
268 template <typename T, typename Info>
269 inline bool
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
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
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
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
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
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
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.
345  }
346 }
347 
348 template <typename T, typename Info>
349 inline int
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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)
Enable_If< Is_Native_Or_Checked< To >::value &&Is_Special< From >::value, Result >::type assign_r(To &to, const From &, Rounding_Dir dir)
bool normal_is_boundary_infinity(Boundary_Type type, const T &x, const Info &)
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_minus_infinity(const T &x)
The computed result is exact.
Definition: Result_defs.hh:81
bool normal_is_reverse_infinity(Boundary_Type type, const T &x, const Info &)
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)
Result set_minus_infinity(Boundary_Type type, T &x, Info &info, bool open=false)
Rounding_Dir
Rounding directions for arithmetic computations.
Result set_plus_infinity(Boundary_Type type, T &x, Info &info, bool open=false)
A positive integer overflow occurred (rounding up).
Definition: Result_defs.hh:111
bool lt(Boundary_Type type1, const T1 &x1, const Info1 &info1, Boundary_Type type2, const T2 &x2, const Info2 &info2)
int infinity_sign(Boundary_Type type, const T &x, const Info &info)
Result
Possible outcomes of a checked arithmetic computation.
Definition: Result_defs.hh:76
From bool Type Type Rounding_Dir To
Result special_set_boundary_infinity(Boundary_Type type, T &, Info &info)
bool gt(Boundary_Type type1, const T1 &x1, const Info1 &info1, Boundary_Type type2, const T2 &x2, const Info2 &info2)
bool is_reverse_infinity(Boundary_Type type, const T &x, const Info &info)
Rounding_Dir round_dir_check(Boundary_Type t, bool check=false)
bool is_domain_inf(Boundary_Type type, const T &x, const Info &info)
Result_Relation result_relation(Result r)
Result set_zero(Boundary_Type to_type, To &to, To_Info &to_info, bool should_shrink)
bool is_minus_infinity(Boundary_Type type, const T &x, const Info &info)
static const Property OPEN(Property::OPEN_)
Not a number result.
Definition: Result_defs.hh:123
The computed result is inexact and rounded down.
Definition: Result_defs.hh:87
static const Property SPECIAL(Property::SPECIAL_)
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)
Result neg_assign(Boundary_Type to_type, To &to, To_Info &to_info, Boundary_Type type, const T &x, const Info &info)
#define PPL_COMPILE_TIME_CHECK(e, msg)
Produces a compilation error if the compile-time constant e does not evaluate to true ...
bool is_open(Boundary_Type type, const T &x, const Info &info)
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)
Equal. This need to be accompanied by a value.
Definition: Result_defs.hh:51
bool is_plus_infinity(Boundary_Type type, const T &x, const Info &info)
bool eq(Boundary_Type type1, const T1 &x1, const Info1 &info1, Boundary_Type type2, const T2 &x2, const Info2 &info2)
Result result_relation_class(Result r)
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)
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_plus_infinity(const T &x)
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)
bool ge(Boundary_Type type1, const T1 &x1, const Info1 &info1, Boundary_Type type2, const T2 &x2, const Info2 &info2)
bool boundary_infinity_is_open(Boundary_Type type, const Info &info)
bool normal_is_open(Boundary_Type type, const T &x, const Info &info)
Result set_unbounded(Boundary_Type type, T &x, Info &info)
The computed result may be inexact and rounded up.
Definition: Result_defs.hh:93
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)
Result complement(Boundary_Type to_type, To &to, To_Info &to_info, Boundary_Type type, const T &x, const Info &info)
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)
Plus_Infinity PLUS_INFINITY
Definition: checked.cc:31
The entire library is confined to this namespace.
Definition: version.hh:61
Minus_Infinity MINUS_INFINITY
Definition: checked.cc:30
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)
The computed result may be inexact and rounded down.
Definition: Result_defs.hh:96
int sgn_b(Boundary_Type type, const T &x, const Info &info)
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)
int sgn(Boundary_Type type, const T &x, const Info &info)
A negative integer overflow occurred (rounding down).
Definition: Result_defs.hh:114
Result min_assign(Boundary_Type to_type, To &to, To_Info &to_info, Boundary_Type type, const T &x, const Info &info)
Result adjust_boundary(Boundary_Type type, T &x, Info &info, bool open, Result r)
bool special_is_open(Boundary_Type, const T &, const Info &)
bool result_representable(Result r)
The computed result is inexact and rounded up.
Definition: Result_defs.hh:84
Result max_assign(Boundary_Type to_type, To &to, To_Info &to_info, Boundary_Type type, const T &x, const Info &info)
bool is_boundary_infinity_closed(Boundary_Type type, const T &x, const Info &info)
bool le(Boundary_Type type1, const T1 &x1, const Info1 &info1, Boundary_Type type2, const T2 &x2, const Info2 &info2)
bool is_domain_sup(Boundary_Type type, const T &x, const Info &info)
bool is_boundary_infinity(Boundary_Type type, const T &x, const Info &info)
Result set_boundary_infinity(Boundary_Type type, T &x, Info &info, bool open=false)