PPL  1.2
Interval_inlines.hh
Go to the documentation of this file.
1 /* Inline functions for the Interval class and its constituents.
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_Interval_inlines_hh
25 #define PPL_Interval_inlines_hh 1
26 
27 namespace Parma_Polyhedra_Library {
28 
29 template <typename Boundary, typename Info>
30 inline memory_size_type
34 }
35 
36 template <typename Boundary, typename Info>
37 inline memory_size_type
39  return sizeof(*this) + external_memory_in_bytes();
40 }
41 
42 template <typename Boundary, typename Info>
43 inline void
45  using std::swap;
46  swap(lower(), y.lower());
47  swap(upper(), y.upper());
48  swap(info(), y.info());
49 }
50 
51 template <typename Boundary, typename Info>
52 inline bool
54  return x.is_empty();
55 }
56 template <typename Boundary, typename Info>
57 inline bool
59  return x.is_singleton();
60 }
61 template <typename Boundary, typename Info>
62 inline int
64  return x.infinity_sign();
65 }
66 
67 namespace Interval_NS {
68 
69 template <typename Boundary, typename Info>
70 inline const Boundary&
72  return x.lower();
73 }
74 template <typename Boundary, typename Info>
75 inline const Boundary&
77  return x.upper();
78 }
79 template <typename Boundary, typename Info>
80 inline const Info&
82  return x.info();
83 }
84 
86  const_bool_nodef(may_be_empty, true);
87  const_bool_nodef(may_contain_infinity, true);
88  const_bool_nodef(check_inexact, false);
89 };
90 
93 
95 
98 
99 template <typename T>
100 inline typename Enable_If<Is_Singleton<T>::value, const T&>::type
101 f_lower(const T& x) {
102  return x;
103 }
104 template <typename T>
105 inline typename Enable_If<Is_Singleton<T>::value, const T&>::type
106 f_upper(const T& x) {
107  return x;
108 }
109 template <typename T>
110 inline typename Enable_If<Is_Singleton<T>::value,
111  const Scalar_As_Interval_Info&>::type
112 f_info(const T&) {
113  return SCALAR_INFO;
114 }
115 template <typename T>
116 inline typename Enable_If<Is_Singleton<T>::value,
118 f_info(const T&, bool open) {
119  return Scalar_As_Interval_Info_Open(open);
120 }
121 
122 template <typename T>
123 inline typename Enable_If<Is_Singleton<T>::value, bool>::type
124 f_is_empty(const T& x) {
125  return is_not_a_number(x);
126 }
127 
128 template <typename T>
129 inline typename Enable_If<Is_Singleton<T>::value, bool>::type
130 f_is_singleton(const T& x) {
131  return !f_is_empty(x);
132 }
133 
134 } // namespace Interval_NS
135 
136 template <typename T>
137 inline typename Enable_If<Is_Singleton<T>::value
138  || Is_Interval<T>::value, bool>::type
139 is_singleton_integer(const T& x) {
140  return is_singleton(x) && is_integer(f_lower(x));
141 }
142 
143 template <typename T>
144 inline typename Enable_If<Is_Singleton<T>::value
145  || Is_Interval<T>::value, bool>::type
146 check_empty_arg(const T& x) {
147  if (f_info(x).may_be_empty) {
148  return f_is_empty(x);
149  }
150  else {
151  PPL_ASSERT(!f_is_empty(x));
152  return false;
153  }
154 }
155 
156 template <typename T1, typename T2>
163  bool>::type
164 operator==(const T1& x, const T2& y) {
165  PPL_ASSERT(f_OK(x));
166  PPL_ASSERT(f_OK(y));
167  if (check_empty_arg(x)) {
168  return check_empty_arg(y);
169  }
170  else if (check_empty_arg(y)) {
171  return false;
172  }
173  return eq(LOWER, f_lower(x), f_info(x), LOWER, f_lower(y), f_info(y))
174  && eq(UPPER, f_upper(x), f_info(x), UPPER, f_upper(y), f_info(y));
175 }
176 
177 template <typename T1, typename T2>
184  bool>::type
185 operator!=(const T1& x, const T2& y) {
186  return !(x == y);
187 }
188 
189 template <typename Boundary, typename Info>
190 template <typename T>
191 inline typename Enable_If<Is_Singleton<T>::value
192  || Is_Interval<T>::value, bool>::type
194  PPL_ASSERT(OK());
195  PPL_ASSERT(f_OK(y));
196  if (check_empty_arg(y)) {
197  return true;
198  }
199  if (check_empty_arg(*this)) {
200  return false;
201  }
202  return le(LOWER, lower(), info(), LOWER, f_lower(y), f_info(y))
203  && ge(UPPER, upper(), info(), UPPER, f_upper(y), f_info(y));
204 }
205 
206 template <typename Boundary, typename Info>
207 template <typename T>
208 inline typename Enable_If<Is_Singleton<T>::value
209  || Is_Interval<T>::value, bool>::type
211  PPL_ASSERT(OK());
212  PPL_ASSERT(f_OK(y));
213  if (check_empty_arg(y)) {
214  return !check_empty_arg(*this);
215  }
216  if (check_empty_arg(*this)) {
217  return false;
218  }
219  return (lt(LOWER, lower(), info(), LOWER, f_lower(y), f_info(y))
220  && ge(UPPER, upper(), info(), UPPER, f_upper(y), f_info(y)))
221  || (le(LOWER, lower(), info(), LOWER, f_lower(y), f_info(y))
222  && gt(UPPER, upper(), info(), UPPER, f_upper(y), f_info(y)));
223 }
224 
225 template <typename Boundary, typename Info>
226 template <typename T>
227 inline typename Enable_If<Is_Singleton<T>::value
228  || Is_Interval<T>::value, bool>::type
230  PPL_ASSERT(OK());
231  PPL_ASSERT(f_OK(y));
232  if (check_empty_arg(*this) || check_empty_arg(y)) {
233  return true;
234  }
235  return gt(LOWER, lower(), info(), UPPER, f_upper(y), f_info(y))
236  || lt(UPPER, upper(), info(), LOWER, f_lower(y), f_info(y));
237 }
238 
239 template <typename To_Boundary, typename To_Info>
240 template <typename From>
244  PPL_ASSERT(f_OK(x));
245  if (check_empty_arg(x)) {
246  return assign(EMPTY);
247  }
248  PPL_DIRTY_TEMP(To_Info, to_info);
249  to_info.clear();
250  const Result rl = Boundary_NS::assign(LOWER, lower(), to_info,
251  LOWER, f_lower(x), f_info(x));
252  const Result ru = Boundary_NS::assign(UPPER, upper(), to_info,
253  UPPER, f_upper(x), f_info(x));
254  assign_or_swap(info(), to_info);
255  PPL_ASSERT(OK());
256  return combine(rl, ru);
257 }
258 
259 template <typename To_Boundary, typename To_Info>
260 template <typename From>
264  PPL_ASSERT(f_OK(x));
265  if (check_empty_arg(*this)) {
266  return assign(x);
267  }
268  if (check_empty_arg(x)) {
269  return combine(V_EQ, V_EQ);
270  }
271  Result rl;
272  Result ru;
273  rl = min_assign(LOWER, lower(), info(), LOWER, f_lower(x), f_info(x));
274  ru = max_assign(UPPER, upper(), info(), UPPER, f_upper(x), f_info(x));
275  PPL_ASSERT(OK());
276  return combine(rl, ru);
277 }
278 
279 template <typename To_Boundary, typename To_Info>
280 template <typename From1, typename From2>
286  PPL_ASSERT(f_OK(x));
287  PPL_ASSERT(f_OK(y));
288  if (check_empty_arg(x)) {
289  return assign(y);
290  }
291  if (check_empty_arg(y)) {
292  return assign(x);
293  }
294  PPL_DIRTY_TEMP(To_Info, to_info);
295  to_info.clear();
296  Result rl;
297  Result ru;
298  rl = min_assign(LOWER, lower(), to_info,
299  LOWER, f_lower(x), f_info(x),
300  LOWER, f_lower(y), f_info(y));
301  ru = max_assign(UPPER, upper(), to_info,
302  UPPER, f_upper(x), f_info(x),
303  UPPER, f_upper(y), f_info(y));
304  assign_or_swap(info(), to_info);
305  PPL_ASSERT(OK());
306  return combine(rl, ru);
307 }
308 
309 template <typename Boundary, typename Info>
310 template <typename Type>
312  || Is_Interval<Type>::value, bool>::type
314  PPL_DIRTY_TEMP(Boundary, b);
315  if (gt(LOWER, lower(), info(), UPPER, f_upper(x), f_info(x))) {
316  b = lower();
317  return eq(LOWER, b, info(), UPPER, f_upper(x), f_info(x));
318  }
319  else if (lt(UPPER, upper(), info(), LOWER, f_lower(x), f_info(x))) {
320  b = upper();
321  return eq(UPPER, b, info(), LOWER, f_lower(x), f_info(x));
322  }
323  return true;
324 }
325 
326 
327 template <typename To_Boundary, typename To_Info>
328 template <typename From>
332  PPL_ASSERT(f_OK(x));
333  max_assign(LOWER, lower(), info(), LOWER, f_lower(x), f_info(x));
334  min_assign(UPPER, upper(), info(), UPPER, f_upper(x), f_info(x));
335  PPL_ASSERT(OK());
336  return I_ANY;
337 }
338 
339 template <typename To_Boundary, typename To_Info>
340 template <typename From1, typename From2>
346  const From2& y) {
347  PPL_ASSERT(f_OK(x));
348  PPL_ASSERT(f_OK(y));
349  PPL_DIRTY_TEMP(To_Info, to_info);
350  to_info.clear();
351  max_assign(LOWER, lower(), to_info,
352  LOWER, f_lower(x), f_info(x),
353  LOWER, f_lower(y), f_info(y));
354  min_assign(UPPER, upper(), to_info,
355  UPPER, f_upper(x), f_info(x),
356  UPPER, f_upper(y), f_info(y));
357  assign_or_swap(info(), to_info);
358  PPL_ASSERT(OK());
359  return I_NOT_EMPTY;
360 }
361 
362 template <typename To_Boundary, typename To_Info>
363 template <typename From>
367  PPL_ASSERT(f_OK(x));
368  if (lt(UPPER, upper(), info(), LOWER, f_lower(x), f_info(x))
369  || gt(LOWER, lower(), info(), UPPER, f_upper(x), f_info(x))) {
370  return combine(V_EQ, V_EQ);
371  }
372  bool nl = ge(LOWER, lower(), info(), LOWER, f_lower(x), f_info(x));
373  bool nu = le(UPPER, upper(), info(), UPPER, f_upper(x), f_info(x));
374  Result rl = V_EQ;
375  Result ru = V_EQ;
376  if (nl) {
377  if (nu) {
378  return assign(EMPTY);
379  }
380  else {
381  info().clear_boundary_properties(LOWER);
382  rl = complement(LOWER, lower(), info(), UPPER, f_upper(x), f_info(x));
383  }
384  }
385  else if (nu) {
386  info().clear_boundary_properties(UPPER);
387  ru = complement(UPPER, upper(), info(), LOWER, f_lower(x), f_info(x));
388  }
389  PPL_ASSERT(OK());
390  return combine(rl, ru);
391 }
392 
393 template <typename To_Boundary, typename To_Info>
394 template <typename From1, typename From2>
400  const From2& y) {
401  PPL_ASSERT(f_OK(x));
402  PPL_ASSERT(f_OK(y));
403  PPL_DIRTY_TEMP(To_Info, to_info);
404  to_info.clear();
405  if (lt(UPPER, f_upper(x), f_info(x), LOWER, f_lower(y), f_info(y))
406  || gt(LOWER, f_lower(x), f_info(x), UPPER, f_upper(y), f_info(y))) {
407  return assign(x);
408  }
409  bool nl = ge(LOWER, f_lower(x), f_info(x), LOWER, f_lower(y), f_info(y));
410  bool nu = le(UPPER, f_upper(x), f_info(x), UPPER, f_upper(y), f_info(y));
411  Result rl = V_EQ;
412  Result ru = V_EQ;
413  if (nl) {
414  if (nu) {
415  return assign(EMPTY);
416  }
417  else {
418  rl = complement(LOWER, lower(), info(), UPPER, f_upper(y), f_info(y));
419  ru = Boundary_NS::assign(UPPER, upper(), info(), UPPER, f_upper(x), f_info(x));
420  }
421  }
422  else if (nu) {
423  ru = complement(UPPER, upper(), info(), LOWER, f_lower(y), f_info(y));
424  rl = Boundary_NS::assign(LOWER, lower(), info(),
425  LOWER, f_lower(x), f_info(x));
426  }
427  assign_or_swap(info(), to_info);
428  PPL_ASSERT(OK());
429  return combine(rl, ru);
430 }
431 
432 template <typename To_Boundary, typename To_Info>
433 template <typename From>
438  PPL_ASSERT(OK());
439  PPL_ASSERT(f_OK(x));
440  if (check_empty_arg(x)) {
441  return assign(EMPTY);
442  }
443  switch (rel) {
444  case LESS_THAN:
445  {
446  if (lt(UPPER, upper(), info(), UPPER, f_upper(x), f_info(x))) {
447  return combine(V_EQ, V_EQ);
448  }
449  info().clear_boundary_properties(UPPER);
450  Boundary_NS::assign(UPPER, upper(), info(),
451  UPPER, f_upper(x), f_info(x), true);
452  return I_ANY;
453  }
454  case LESS_OR_EQUAL:
455  {
456  if (le(UPPER, upper(), info(), UPPER, f_upper(x), f_info(x))) {
457  return combine(V_EQ, V_EQ);
458  }
459  info().clear_boundary_properties(UPPER);
460  Boundary_NS::assign(UPPER, upper(), info(),
461  UPPER, f_upper(x), f_info(x));
462  return I_ANY;
463  }
464  case GREATER_THAN:
465  {
466  if (gt(LOWER, lower(), info(), LOWER, f_lower(x), f_info(x))) {
467  return combine(V_EQ, V_EQ);
468  }
469  info().clear_boundary_properties(LOWER);
470  Boundary_NS::assign(LOWER, lower(), info(),
471  LOWER, f_lower(x), f_info(x), true);
472  return I_ANY;
473  }
474  case GREATER_OR_EQUAL:
475  {
476  if (ge(LOWER, lower(), info(), LOWER, f_lower(x), f_info(x))) {
477  return combine(V_EQ, V_EQ);
478  }
479  info().clear_boundary_properties(LOWER);
480  Boundary_NS::assign(LOWER, lower(), info(),
481  LOWER, f_lower(x), f_info(x));
482  return I_ANY;
483  }
484  case EQUAL:
485  return intersect_assign(x);
486  case NOT_EQUAL:
487  {
488  if (!f_is_singleton(x)) {
489  return combine(V_EQ, V_EQ);
490  }
491  if (check_empty_arg(*this)) {
492  return I_EMPTY;
493  }
494  if (eq(LOWER, lower(), info(), LOWER, f_lower(x), f_info(x))) {
495  remove_inf();
496  }
497  if (eq(UPPER, upper(), info(), UPPER, f_upper(x), f_info(x))) {
498  remove_sup();
499  }
500  return I_ANY;
501  }
502  default:
503  PPL_UNREACHABLE;
504  return I_EMPTY;
505  }
506 }
507 
508 template <typename To_Boundary, typename To_Info>
509 template <typename From>
513  const From& x) {
514  PPL_ASSERT(OK());
515  PPL_ASSERT(f_OK(x));
516  if (check_empty_arg(x)) {
517  return combine(V_EQ, V_EQ);
518  }
519  switch (rel) {
520  case LESS_THAN:
521  {
522  if (lt(UPPER, upper(), info(), LOWER, f_lower(x), f_info(x))) {
523  return combine(V_EQ, V_EQ);
524  }
525  info().clear_boundary_properties(UPPER);
526  Result ru = Boundary_NS::assign(UPPER, upper(), info(),
528  !is_open(LOWER, f_lower(x), f_info(x)));
529  PPL_USED(ru);
530  return I_ANY;
531  }
532  case LESS_OR_EQUAL:
533  {
534  if (le(UPPER, upper(), info(), LOWER, f_lower(x), f_info(x))) {
535  return combine(V_EQ, V_EQ);
536  }
537  info().clear_boundary_properties(UPPER);
538  Result ru = Boundary_NS::assign(UPPER, upper(), info(),
539  LOWER, f_lower(x), SCALAR_INFO);
540  PPL_USED(ru);
541  return I_ANY;
542  }
543  case GREATER_THAN:
544  {
545  if (gt(LOWER, lower(), info(), UPPER, f_upper(x), f_info(x))) {
546  return combine(V_EQ, V_EQ);
547  }
548  info().clear_boundary_properties(LOWER);
549  Result rl = Boundary_NS::assign(LOWER, lower(), info(),
551  !is_open(UPPER, f_upper(x), f_info(x)));
552  PPL_USED(rl);
553  return I_ANY;
554  }
555  case GREATER_OR_EQUAL:
556  {
557  if (ge(LOWER, lower(), info(), UPPER, f_upper(x), f_info(x))) {
558  return combine(V_EQ, V_EQ);
559  }
560  info().clear_boundary_properties(LOWER);
561  Result rl = Boundary_NS::assign(LOWER, lower(), info(),
562  UPPER, f_upper(x), SCALAR_INFO);
563  PPL_USED(rl);
564  return I_ANY;
565  }
566  case EQUAL:
567  if (!f_is_singleton(x)) {
568  return assign(EMPTY);
569  }
570  return intersect_assign(x);
571  case NOT_EQUAL:
572  {
573  if (check_empty_arg(*this)) {
574  return I_EMPTY;
575  }
576  if (eq(LOWER, lower(), info(), LOWER, f_lower(x), f_info(x))) {
577  remove_inf();
578  }
579  if (eq(UPPER, upper(), info(), UPPER, f_upper(x), f_info(x))) {
580  remove_sup();
581  }
582  return I_ANY;
583  }
584  default:
585  PPL_UNREACHABLE;
586  return I_EMPTY;
587  }
588 }
589 
590 template <typename To_Boundary, typename To_Info>
591 template <typename From>
595  PPL_ASSERT(f_OK(x));
596  if (check_empty_arg(x)) {
597  return assign(EMPTY);
598  }
599  PPL_DIRTY_TEMP(To_Info, to_info);
600  to_info.clear();
601  Result rl;
602  Result ru;
603  PPL_DIRTY_TEMP(To_Boundary, to_lower);
604  rl = Boundary_NS::neg_assign(LOWER, to_lower, to_info, UPPER, f_upper(x), f_info(x));
605  ru = Boundary_NS::neg_assign(UPPER, upper(), to_info, LOWER, f_lower(x), f_info(x));
606  assign_or_swap(lower(), to_lower);
607  assign_or_swap(info(), to_info);
608  PPL_ASSERT(OK());
609  return combine(rl, ru);
610 }
611 
612 template <typename To_Boundary, typename To_Info>
613 template <typename From1, typename From2>
619  PPL_ASSERT(f_OK(x));
620  PPL_ASSERT(f_OK(y));
621  if (check_empty_arg(x) || check_empty_arg(y)) {
622  return assign(EMPTY);
623  }
624  int inf_sign = Parma_Polyhedra_Library::infinity_sign(x);
625  if (inf_sign != 0) {
626  if (Parma_Polyhedra_Library::infinity_sign(y) == -inf_sign) {
627  return assign(EMPTY);
628  }
629  }
630  else {
632  }
633  if (inf_sign < 0) {
634  return assign(MINUS_INFINITY);
635  }
636  else if (inf_sign > 0) {
637  return assign(PLUS_INFINITY);
638  }
639  PPL_DIRTY_TEMP(To_Info, to_info);
640  to_info.clear();
641  Result rl = Boundary_NS::add_assign(LOWER, lower(), to_info,
642  LOWER, f_lower(x), f_info(x),
643  LOWER, f_lower(y), f_info(y));
644  Result ru = Boundary_NS::add_assign(UPPER, upper(), to_info,
645  UPPER, f_upper(x), f_info(x),
646  UPPER, f_upper(y), f_info(y));
647  assign_or_swap(info(), to_info);
648  PPL_ASSERT(OK());
649  return combine(rl, ru);
650 }
651 
652 template <typename To_Boundary, typename To_Info>
653 template <typename From1, typename From2>
659  PPL_ASSERT(f_OK(x));
660  PPL_ASSERT(f_OK(y));
661  if (check_empty_arg(x) || check_empty_arg(y)) {
662  return assign(EMPTY);
663  }
664  int inf_sign = Parma_Polyhedra_Library::infinity_sign(x);
665  if (inf_sign != 0) {
666  if (Parma_Polyhedra_Library::infinity_sign(y) == inf_sign) {
667  return assign(EMPTY);
668  }
669  }
670  else {
672  }
673  if (inf_sign < 0) {
674  return assign(MINUS_INFINITY);
675  }
676  else if (inf_sign > 0) {
677  return assign(PLUS_INFINITY);
678  }
679  PPL_DIRTY_TEMP(To_Info, to_info);
680  to_info.clear();
681  Result rl;
682  Result ru;
683  PPL_DIRTY_TEMP(To_Boundary, to_lower);
684  rl = Boundary_NS::sub_assign(LOWER, to_lower, to_info,
685  LOWER, f_lower(x), f_info(x),
686  UPPER, f_upper(y), f_info(y));
687  ru = Boundary_NS::sub_assign(UPPER, upper(), to_info,
688  UPPER, f_upper(x), f_info(x),
689  LOWER, f_lower(y), f_info(y));
690  assign_or_swap(lower(), to_lower);
691  assign_or_swap(info(), to_info);
692  PPL_ASSERT(OK());
693  return combine(rl, ru);
694 }
695 
708 template <typename To_Boundary, typename To_Info>
709 template <typename From1, typename From2>
715  PPL_ASSERT(f_OK(x));
716  PPL_ASSERT(f_OK(y));
717  if (check_empty_arg(x) || check_empty_arg(y)) {
718  return assign(EMPTY);
719  }
720  int xls = sgn_b(LOWER, f_lower(x), f_info(x));
721  int xus = (xls > 0) ? 1 : sgn_b(UPPER, f_upper(x), f_info(x));
722  int yls = sgn_b(LOWER, f_lower(y), f_info(y));
723  int yus = (yls > 0) ? 1 : sgn_b(UPPER, f_upper(y), f_info(y));
724  int inf_sign = Parma_Polyhedra_Library::infinity_sign(x);
725  int ls;
726  int us;
727  if (inf_sign != 0) {
728  ls = yls;
729  us = yus;
730  goto inf;
731  }
732  else {
734  if (inf_sign != 0) {
735  ls = xls;
736  us = xus;
737  inf:
738  if (ls == 0 && us == 0) {
739  return assign(EMPTY);
740  }
741  if (ls == -us) {
742  return set_infinities();
743  }
744  if (ls < 0 || us < 0) {
745  inf_sign = -inf_sign;
746  }
747  if (inf_sign < 0) {
748  return assign(MINUS_INFINITY);
749  }
750  else {
751  return assign(PLUS_INFINITY);
752  }
753  }
754  }
755 
756  PPL_DIRTY_TEMP(To_Info, to_info);
757  to_info.clear();
758  Result rl;
759  Result ru;
760  PPL_DIRTY_TEMP(To_Boundary, to_lower);
761 
762  if (xls >= 0) {
763  if (yls >= 0) {
764  // 0 <= xl <= xu, 0 <= yl <= yu
765  rl = mul_assign_z(LOWER, to_lower, to_info,
766  LOWER, f_lower(x), f_info(x), xls,
767  LOWER, f_lower(y), f_info(y), yls);
768  ru = mul_assign_z(UPPER, upper(), to_info,
769  UPPER, f_upper(x), f_info(x), xus,
770  UPPER, f_upper(y), f_info(y), yus);
771  }
772  else if (yus <= 0) {
773  // 0 <= xl <= xu, yl <= yu <= 0
774  rl = mul_assign_z(LOWER, to_lower, to_info,
775  UPPER, f_upper(x), f_info(x), xus,
776  LOWER, f_lower(y), f_info(y), yls);
777  ru = mul_assign_z(UPPER, upper(), to_info,
778  LOWER, f_lower(x), f_info(x), xls,
779  UPPER, f_upper(y), f_info(y), yus);
780  }
781  else {
782  // 0 <= xl <= xu, yl < 0 < yu
783  rl = mul_assign_z(LOWER, to_lower, to_info,
784  UPPER, f_upper(x), f_info(x), xus,
785  LOWER, f_lower(y), f_info(y), yls);
786  ru = mul_assign_z(UPPER, upper(), to_info,
787  UPPER, f_upper(x), f_info(x), xus,
788  UPPER, f_upper(y), f_info(y), yus);
789  }
790  }
791  else if (xus <= 0) {
792  if (yls >= 0) {
793  // xl <= xu <= 0, 0 <= yl <= yu
794  rl = mul_assign_z(LOWER, to_lower, to_info,
795  LOWER, f_lower(x), f_info(x), xls,
796  UPPER, f_upper(y), f_info(y), yus);
797  ru = mul_assign_z(UPPER, upper(), to_info,
798  UPPER, f_upper(x), f_info(x), xus,
799  LOWER, f_lower(y), f_info(y), yls);
800  }
801  else if (yus <= 0) {
802  // xl <= xu <= 0, yl <= yu <= 0
803  rl = mul_assign_z(LOWER, to_lower, to_info,
804  UPPER, f_upper(x), f_info(x), xus,
805  UPPER, f_upper(y), f_info(y), yus);
806  ru = mul_assign_z(UPPER, upper(), to_info,
807  LOWER, f_lower(x), f_info(x), xls,
808  LOWER, f_lower(y), f_info(y), yls);
809  }
810  else {
811  // xl <= xu <= 0, yl < 0 < yu
812  rl = mul_assign_z(LOWER, to_lower, to_info,
813  LOWER, f_lower(x), f_info(x), xls,
814  UPPER, f_upper(y), f_info(y), yus);
815  ru = mul_assign_z(UPPER, upper(), to_info,
816  LOWER, f_lower(x), f_info(x), xls,
817  LOWER, f_lower(y), f_info(y), yls);
818  }
819  }
820  else if (yls >= 0) {
821  // xl < 0 < xu, 0 <= yl <= yu
822  rl = mul_assign_z(LOWER, to_lower, to_info,
823  LOWER, f_lower(x), f_info(x), xls,
824  UPPER, f_upper(y), f_info(y), yus);
825  ru = mul_assign_z(UPPER, upper(), to_info,
826  UPPER, f_upper(x), f_info(x), xus,
827  UPPER, f_upper(y), f_info(y), yus);
828  }
829  else if (yus <= 0) {
830  // xl < 0 < xu, yl <= yu <= 0
831  rl = mul_assign_z(LOWER, to_lower, to_info,
832  UPPER, f_upper(x), f_info(x), xus,
833  LOWER, f_lower(y), f_info(y), yls);
834  ru = mul_assign_z(UPPER, upper(), to_info,
835  LOWER, f_lower(x), f_info(x), xls,
836  LOWER, f_lower(y), f_info(y), yls);
837  }
838  else {
839  // xl < 0 < xu, yl < 0 < yu
840  PPL_DIRTY_TEMP(To_Boundary, tmp);
841  PPL_DIRTY_TEMP(To_Info, tmp_info);
842  tmp_info.clear();
843  Result tmp_r;
844  tmp_r = Boundary_NS::mul_assign(LOWER, tmp, tmp_info,
845  UPPER, f_upper(x), f_info(x),
846  LOWER, f_lower(y), f_info(y));
847  rl = Boundary_NS::mul_assign(LOWER, to_lower, to_info,
848  LOWER, f_lower(x), f_info(x),
849  UPPER, f_upper(y), f_info(y));
850  if (gt(LOWER, to_lower, to_info, LOWER, tmp, tmp_info)) {
851  to_lower = tmp;
852  rl = tmp_r;
853  }
854  tmp_info.clear();
855  tmp_r = Boundary_NS::mul_assign(UPPER, tmp, tmp_info,
856  UPPER, f_upper(x), f_info(x),
857  UPPER, f_upper(y), f_info(y));
858  ru = Boundary_NS::mul_assign(UPPER, upper(), to_info,
859  LOWER, f_lower(x), f_info(x),
860  LOWER, f_lower(y), f_info(y));
861  if (lt(UPPER, upper(), to_info, UPPER, tmp, tmp_info)) {
862  upper() = tmp;
863  ru = tmp_r;
864  }
865  }
866  assign_or_swap(lower(), to_lower);
867  assign_or_swap(info(), to_info);
868  PPL_ASSERT(OK());
869  return combine(rl, ru);
870 }
871 
883 template <typename To_Boundary, typename To_Info>
884 template <typename From1, typename From2>
890  PPL_ASSERT(f_OK(x));
891  PPL_ASSERT(f_OK(y));
892  if (check_empty_arg(x) || check_empty_arg(y)) {
893  return assign(EMPTY);
894  }
895  int yls = sgn_b(LOWER, f_lower(y), f_info(y));
896  int yus = (yls > 0) ? 1 : sgn_b(UPPER, f_upper(y), f_info(y));
897  if (yls == 0 && yus == 0) {
898  return assign(EMPTY);
899  }
900  int inf_sign = Parma_Polyhedra_Library::infinity_sign(x);
901  if (inf_sign != 0) {
903  return assign(EMPTY);
904  }
905  if (yls == -yus) {
906  return set_infinities();
907  }
908  if (yls < 0 || yus < 0) {
909  inf_sign = -inf_sign;
910  }
911  if (inf_sign < 0) {
912  return assign(MINUS_INFINITY);
913  }
914  else {
915  return assign(PLUS_INFINITY);
916  }
917  }
918  int xls = sgn_b(LOWER, f_lower(x), f_info(x));
919  int xus = (xls > 0) ? 1 : sgn_b(UPPER, f_upper(x), f_info(x));
920 
921  PPL_DIRTY_TEMP(To_Info, to_info);
922  to_info.clear();
923  Result rl;
924  Result ru;
925  PPL_DIRTY_TEMP(To_Boundary, to_lower);
926  if (yls >= 0) {
927  if (xls >= 0) {
928  rl = div_assign_z(LOWER, to_lower, to_info,
929  LOWER, f_lower(x), f_info(x), xls,
930  UPPER, f_upper(y), f_info(y), yus);
931  ru = div_assign_z(UPPER, upper(), to_info,
932  UPPER, f_upper(x), f_info(x), xus,
933  LOWER, f_lower(y), f_info(y), yls);
934  }
935  else if (xus <= 0) {
936  rl = div_assign_z(LOWER, to_lower, to_info,
937  LOWER, f_lower(x), f_info(x), xls,
938  LOWER, f_lower(y), f_info(y), yls);
939  ru = div_assign_z(UPPER, upper(), to_info,
940  UPPER, f_upper(x), f_info(x), xus,
941  UPPER, f_upper(y), f_info(y), yus);
942  }
943  else {
944  rl = div_assign_z(LOWER, to_lower, to_info,
945  LOWER, f_lower(x), f_info(x), xls,
946  LOWER, f_lower(y), f_info(y), yls);
947  ru = div_assign_z(UPPER, upper(), to_info,
948  UPPER, f_upper(x), f_info(x), xus,
949  LOWER, f_lower(y), f_info(y), yls);
950  }
951  }
952  else if (yus <= 0) {
953  if (xls >= 0) {
954  rl = div_assign_z(LOWER, to_lower, to_info,
955  UPPER, f_upper(x), f_info(x), xus,
956  UPPER, f_upper(y), f_info(y), yus);
957  ru = div_assign_z(UPPER, upper(), to_info,
958  LOWER, f_lower(x), f_info(x), xls,
959  LOWER, f_lower(y), f_info(y), yls);
960  }
961  else if (xus <= 0) {
962  rl = div_assign_z(LOWER, to_lower, to_info,
963  UPPER, f_upper(x), f_info(x), xus,
964  LOWER, f_lower(y), f_info(y), yls);
965  ru = div_assign_z(UPPER, upper(), to_info,
966  LOWER, f_lower(x), f_info(x), xls,
967  UPPER, f_upper(y), f_info(y), yus);
968  }
969  else {
970  rl = div_assign_z(LOWER, to_lower, to_info,
971  UPPER, f_upper(x), f_info(x), xus,
972  UPPER, f_upper(y), f_info(y), yus);
973  ru = div_assign_z(UPPER, upper(), to_info,
974  LOWER, f_lower(x), f_info(x), xls,
975  UPPER, f_upper(y), f_info(y), yus);
976  }
977  }
978  else {
979  return static_cast<I_Result>(assign(UNIVERSE) | I_SINGULARITIES);
980  }
981  assign_or_swap(lower(), to_lower);
982  assign_or_swap(info(), to_info);
983  PPL_ASSERT(OK());
984  return combine(rl, ru);
985 }
986 
987 template <typename B, typename Info, typename T>
989 operator+(const Interval<B, Info>& x, const T& y) {
991  z.add_assign(x, y);
992  return z;
993 }
994 
995 template <typename B, typename Info, typename T>
996 inline typename Enable_If<Is_Singleton<T>::value, Interval<B, Info> >::type
997 operator+(const T& x, const Interval<B, Info>& y) {
999  z.add_assign(x, y);
1000  return z;
1001 }
1002 
1003 template <typename B, typename Info>
1004 inline Interval<B, Info>
1007  z.add_assign(x, y);
1008  return z;
1009 }
1010 
1011 template <typename B, typename Info, typename T>
1012 inline typename Enable_If<Is_Singleton<T>::value, Interval<B, Info> >::type
1013 operator-(const Interval<B, Info>& x, const T& y) {
1015  z.sub_assign(x, y);
1016  return z;
1017 }
1018 
1019 template <typename B, typename Info, typename T>
1020 inline typename Enable_If<Is_Singleton<T>::value, Interval<B, Info> >::type
1021 operator-(const T& x, const Interval<B, Info>& y) {
1023  z.sub_assign(x, y);
1024  return z;
1025 }
1026 
1027 template <typename B, typename Info>
1028 inline Interval<B, Info>
1031  z.sub_assign(x, y);
1032  return z;
1033 }
1034 
1035 template <typename B, typename Info, typename T>
1036 inline typename Enable_If<Is_Singleton<T>::value, Interval<B, Info> >::type
1037 operator*(const Interval<B, Info>& x, const T& y) {
1039  z.mul_assign(x, y);
1040  return z;
1041 }
1042 
1043 template <typename B, typename Info, typename T>
1044 inline typename Enable_If<Is_Singleton<T>::value, Interval<B, Info> >::type
1045 operator*(const T& x, const Interval<B, Info>& y) {
1047  z.mul_assign(x, y);
1048  return z;
1049 }
1050 
1051 template <typename B, typename Info>
1052 inline Interval<B, Info>
1055  z.mul_assign(x, y);
1056  return z;
1057 }
1058 
1059 template <typename B, typename Info, typename T>
1060 inline typename Enable_If<Is_Singleton<T>::value, Interval<B, Info> >::type
1061 operator/(const Interval<B, Info>& x, const T& y) {
1063  z.div_assign(x, y);
1064  return z;
1065 }
1066 
1067 template <typename B, typename Info, typename T>
1068 inline typename Enable_If<Is_Singleton<T>::value, Interval<B, Info> >::type
1069 operator/(const T& x, const Interval<B, Info>& y) {
1071  z.div_assign(x, y);
1072  return z;
1073 }
1074 
1075 template <typename B, typename Info>
1076 inline Interval<B, Info>
1079  z.div_assign(x, y);
1080  return z;
1081 }
1082 
1083 template <typename Boundary, typename Info>
1084 inline std::ostream&
1085 operator<<(std::ostream& os, const Interval<Boundary, Info>& x) {
1086  if (check_empty_arg(x)) {
1087  return os << "[]";
1088  }
1089  if (x.is_singleton()) {
1090  output(os, x.lower(), Numeric_Format(), ROUND_NOT_NEEDED);
1091  return os;
1092  }
1093  os << (x.lower_is_open() ? "(" : "[");
1094  if (x.info().get_boundary_property(LOWER, SPECIAL)) {
1095  os << "-inf";
1096  }
1097  else {
1098  output(os, x.lower(), Numeric_Format(), ROUND_NOT_NEEDED);
1099  }
1100  os << ", ";
1101  if (x.info().get_boundary_property(UPPER, SPECIAL)) {
1102  os << "+inf";
1103  }
1104  else {
1105  output(os, x.upper(), Numeric_Format(), ROUND_NOT_NEEDED);
1106  }
1107  os << (x.upper_is_open() ? ")" : "]");
1108  return os;
1109 }
1110 
1111 template <typename Boundary, typename Info>
1112 inline void
1115  s << "info ";
1116  info().ascii_dump(s);
1117  s << " lower ";
1118  ascii_dump(s, lower());
1119  s << " upper ";
1120  ascii_dump(s, upper());
1121  s << '\n';
1122 }
1123 
1124 template <typename Boundary, typename Info>
1125 inline bool
1128  std::string str;
1129  if (!(s >> str) || str != "info") {
1130  return false;
1131  }
1132  if (!info().ascii_load(s)) {
1133  return false;
1134  }
1135  if (!(s >> str) || str != "lower") {
1136  return false;
1137  }
1138  if (!ascii_load(s, lower())) {
1139  return false;
1140  }
1141  if (!(s >> str) || str != "upper") {
1142  return false;
1143  }
1144  if (!ascii_load(s, upper())) {
1145  return false;
1146  }
1147  PPL_ASSERT(OK());
1148  return true;
1149 }
1150 
1156 template <typename Interval_Boundary_Type> struct Select_Temp_Boundary_Type;
1157 
1158 template <typename Interval_Boundary_Type>
1160  typedef Interval_Boundary_Type type;
1161 };
1162 
1163 #if PPL_SUPPORTED_DOUBLE
1164 template <>
1165 struct Select_Temp_Boundary_Type<float> {
1166  typedef double type;
1167 };
1168 #endif
1169 
1170 template <>
1172  typedef signed long long type;
1173 };
1174 
1175 template <>
1177  typedef signed long long type;
1178 };
1179 
1180 template <>
1182  typedef signed long long type;
1183 };
1184 
1185 template <>
1187  typedef signed long long type;
1188 };
1189 
1190 template <>
1192  typedef signed long long type;
1193 };
1194 
1195 template <>
1197  typedef signed long long type;
1198 };
1199 
1200 template <>
1201 struct Select_Temp_Boundary_Type<unsigned int> {
1202  typedef signed long long type;
1203 };
1204 
1205 template <>
1207  typedef signed long long type;
1208 };
1209 
1210 template <>
1212  typedef signed long long type;
1213 };
1214 
1215 template <>
1217  typedef signed long long type;
1218 };
1219 
1221 template <typename Boundary, typename Info>
1222 inline void
1224  x.m_swap(y);
1225 }
1226 
1227 } // namespace Parma_Polyhedra_Library
1228 
1229 #endif // !defined(PPL_Interval_inlines_hh)
Enable_If< Is_Singleton< T >::value, Interval< B, Info > >::type operator*(const Interval< B, Info > &x, const T &y)
Enable_If< Is_Singleton< Type >::value||Is_Interval< Type >::value, bool >::type can_be_exactly_joined_to(const Type &x) const
bool operator!=(const Box< ITV > &x, const Box< ITV > &y)
Definition: Box_inlines.hh:264
The empty element, i.e., the empty set.
The computed result is exact.
Definition: Result_defs.hh:81
Enable_If< Is_Singleton< T >::value||Is_Interval< T >::value, bool >::type is_singleton_integer(const T &x)
Interval_Info_Null< Scalar_As_Interval_Policy > Scalar_As_Interval_Info
void swap(CO_Tree &x, CO_Tree &y)
I_Result
The result of an operation on intervals.
bool f_is_singleton(const Interval< Boundary, Info > &x)
void swap(Interval< Boundary, Info > &x, Interval< Boundary, Info > &y)
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)
Enable_If< Is_Singleton< T >::value, bool >::type f_is_empty(const T &x)
void ascii_dump(std::ostream &s) const
Helper class to select the appropriate numerical type to perform boundary computations so as to reduc...
memory_size_type external_memory_in_bytes() const
Returns the size in bytes of the memory managed by *this.
Enable_If< Has_Assign_Or_Swap< T >::value, void >::type assign_or_swap(T &to, T &from)
Enable_If< Is_Native_Or_Checked< T >::value, void >::type ascii_dump(std::ostream &s, const T &t)
bool lt(Boundary_Type type1, const T1 &x1, const Info1 &info1, Boundary_Type type2, const T2 &x2, const Info2 &info2)
Result may be empty or not empty.
Enable_If< Is_Singleton< From >::value||Is_Interval< From >::value, I_Result >::type difference_assign(const From &x)
Assigns to *this the smallest interval containing the set-theoretic difference of *this and x...
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_integer(const T &x)
void m_swap(Interval &y)
Swaps *this with y.
const Boundary & f_upper(const Interval< Boundary, Info > &x)
Result
Possible outcomes of a checked arithmetic computation.
Definition: Result_defs.hh:76
bool gt(Boundary_Type type1, const T1 &x1, const Info1 &info1, Boundary_Type type2, const T2 &x2, const Info2 &info2)
Operation is undefined for some combination of values.
signed signed signed signed signed char signed signed signed signed signed int signed long long
void max_assign(N &x, const N &y)
Assigns to x the maximum between x and y.
Enable_If< Is_Singleton< T >::value, Interval< B, Info > >::type operator/(const Interval< B, Info > &x, const T &y)
signed signed signed signed signed char signed signed signed signed signed int signed long signed long signed long signed long signed long long unsigned short
memory_size_type total_memory_in_bytes() const
Returns the total size in bytes of the memory occupied by *this.
Enable_If< Is_Singleton< T >::value||Is_Interval< T >::value, bool >::type check_empty_arg(const T &x)
Enable_If< Is_Singleton< From >::value||Is_Interval< From >::value, I_Result >::type refine_universal(Relation_Symbol rel, const From &x)
Refines to so that it satisfies the universal relation rel with x.
Enable_If< Is_Singleton< T >::value||Is_Interval< T >::value, bool >::type contains(const T &y) const
Enable_If<((Is_Singleton< From1 >::value||Is_Interval< From1 >::value)&&(Is_Singleton< From2 >::value||Is_Interval< From2 >::value)), I_Result >::type sub_assign(const From1 &x, const From2 &y)
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)
Enable_If< Is_Singleton< From >::value||Is_Interval< From >::value, I_Result >::type refine_existential(Relation_Symbol rel, const From &x)
Refines to according to the existential relation rel with x.
I_Result assign(Degenerate_Element e)
Enable_If<((Is_Singleton< From1 >::value||Is_Interval< From1 >::value)&&(Is_Singleton< From2 >::value||Is_Interval< From2 >::value)), I_Result >::type add_assign(const From1 &x, const From2 &y)
bool is_open(Boundary_Type type, const T &x, const Info &info)
Relation_Symbol
Relation symbols.
From bool Type Type Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir unsigned int
Enable_If< Is_Singleton< T >::value||Is_Interval< T >::value, bool >::type is_disjoint_from(const T &y) const
Enable_If< Is_Singleton< T >::value, const T & >::type f_lower(const T &x)
const Info & f_info(const Interval< Boundary, Info > &x)
Enable_If< Is_Native< T >::value, memory_size_type >::type external_memory_in_bytes(const T &)
For native types, returns the size in bytes of the memory managed by the type of the (unused) paramet...
bool eq(Boundary_Type type1, const T1 &x1, const Info1 &info1, Boundary_Type type2, const T2 &x2, const Info2 &info2)
const Scalar_As_Interval_Info SCALAR_INFO
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type is_not_a_number(const T &x)
Enable_If< Is_Native_Or_Checked< T >::value, bool >::type ascii_load(std::istream &s, T &t)
Enable_If< Is_Singleton< T >::value, bool >::type f_is_singleton(const T &x)
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_Singleton< From >::value||Is_Interval< From >::value, I_Result >::type neg_assign(const From &x)
Coefficient value
Definition: PIP_Tree.cc:618
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)
#define PPL_DIRTY_TEMP(T, id)
Result complement(Boundary_Type to_type, To &to, To_Info &to_info, Boundary_Type type, const T &x, const Info &info)
The universe element, i.e., the whole vector space.
A generic, not necessarily closed, possibly restricted interval.
From bool Type Type Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir From1
const Boundary & f_lower(const Interval< Boundary, Info > &x)
Enable_If<((Is_Singleton< From1 >::value||Is_Interval< From1 >::value)&&(Is_Singleton< From2 >::value||Is_Interval< From2 >::value)), I_Result >::type div_assign(const From1 &x, const From2 &y)
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
Enable_If< Is_Singleton< From >::value||Is_Interval< From >::value, I_Result >::type intersect_assign(const From &x)
The entire library is confined to this namespace.
Definition: version.hh:61
Enable_If< Is_Singleton< T >::value, Interval< B, Info > >::type operator+(const Interval< B, Info > &x, const T &y)
Enable_If< Is_Singleton< T >::value, Scalar_As_Interval_Info_Open >::type f_info(const T &, bool open)
Minus_Infinity MINUS_INFINITY
Definition: checked.cc:30
Enable_If< Has_OK< T >::value, bool >::type f_OK(const T &to)
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)
From bool Type Type Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir From2
Enable_If< Is_Singleton< T >::value||Is_Interval< T >::value, bool >::type strictly_contains(const T &y) const
Enable_If< Is_Singleton< From >::value||Is_Interval< From >::value, I_Result >::type join_assign(const From &x)
I_Result combine(Result l, Result u)
bool f_is_empty(const Interval< Boundary, Info > &x)
From bool Type Type Rounding_Dir From
int sgn_b(Boundary_Type type, const T &x, const Info &info)
Enable_If<((Is_Singleton< From1 >::value||Is_Interval< From1 >::value)&&(Is_Singleton< From2 >::value||Is_Interval< From2 >::value)), I_Result >::type mul_assign(const From1 &x, const From2 &y)
Interval_Info_Null_Open< Scalar_As_Interval_Policy > Scalar_As_Interval_Info_Open
#define PPL_USED(v)
No-op macro that allows to avoid unused variable warnings from the compiler.
Definition: compiler.hh:39
bool operator==(const Box< ITV > &x, const Box< ITV > &y)
Enable_If< Is_Singleton< T >::value, Interval< B, Info > >::type operator-(const Interval< B, Info > &x, const T &y)
size_t memory_size_type
An unsigned integral type for representing memory size in bytes.
Enable_If< Is_Singleton< T >::value, const T & >::type f_upper(const T &x)
A class that provides a type member called type equivalent to T if and only if b is true...
Enable_If< Is_Native_Or_Checked< T >::value, int >::type infinity_sign(const T &x)
void min_assign(N &x, const N &y)
Assigns to x the minimum between x and y.
bool le(Boundary_Type type1, const T1 &x1, const Info1 &info1, Boundary_Type type2, const T2 &x2, const Info2 &info2)