PPL  1.2
checked_inlines.hh
Go to the documentation of this file.
1 /* Abstract checked arithmetic functions: fall-backs.
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_checked_inlines_hh
25 #define PPL_checked_inlines_hh 1
26 
27 #include "globals_types.hh"
28 #include "meta_programming.hh"
29 #include "C_Integer.hh"
30 #include "assertions.hh"
31 
38 #define PPL_LT_SILENT(a, b) ((a) < (b))
39 #define PPL_GT_SILENT(a, b) ((a) > (b))
40 
41 namespace Parma_Polyhedra_Library {
42 
43 namespace Checked {
44 
45 template <typename T1, typename T2>
46 struct Safe_Conversion : public False {
47 };
48 template <typename T>
49 struct Safe_Conversion<T, T> : public True {
50 };
51 
52 #define PPL_SAFE_CONVERSION(To, From) \
53  template <> struct Safe_Conversion<PPL_U(To), PPL_U(From)> \
54  : public True { }
55 
56 #if PPL_CXX_PLAIN_CHAR_IS_SIGNED
57 PPL_SAFE_CONVERSION(signed short, char);
58 #endif
59 PPL_SAFE_CONVERSION(signed short, signed char);
60 #if PPL_SIZEOF_CHAR < PPL_SIZEOF_SHORT
61 #if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
62 PPL_SAFE_CONVERSION(signed short, char);
63 #endif
64 PPL_SAFE_CONVERSION(signed short, unsigned char);
65 #endif
66 
67 #if PPL_CXX_PLAIN_CHAR_IS_SIGNED
68 PPL_SAFE_CONVERSION(signed int, char);
69 #endif
70 PPL_SAFE_CONVERSION(signed int, signed char);
71 PPL_SAFE_CONVERSION(signed int, signed short);
72 #if PPL_SIZEOF_CHAR < PPL_SIZEOF_INT
73 #if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
74 PPL_SAFE_CONVERSION(signed int, char);
75 #endif
76 PPL_SAFE_CONVERSION(signed int, unsigned char);
77 #endif
78 #if PPL_SIZEOF_SHORT < PPL_SIZEOF_INT
79 PPL_SAFE_CONVERSION(signed int, unsigned short);
80 #endif
81 
82 #if PPL_CXX_PLAIN_CHAR_IS_SIGNED
83 PPL_SAFE_CONVERSION(signed long, char);
84 #endif
85 PPL_SAFE_CONVERSION(signed long, signed char);
86 PPL_SAFE_CONVERSION(signed long, signed short);
87 PPL_SAFE_CONVERSION(signed long, signed int);
88 #if PPL_SIZEOF_CHAR < PPL_SIZEOF_LONG
89 #if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
90 PPL_SAFE_CONVERSION(signed long, char);
91 #endif
92 PPL_SAFE_CONVERSION(signed long, unsigned char);
93 #endif
94 #if PPL_SIZEOF_SHORT < PPL_SIZEOF_LONG
95 PPL_SAFE_CONVERSION(signed long, unsigned short);
96 #endif
97 #if PPL_SIZEOF_INT < PPL_SIZEOF_LONG
98 PPL_SAFE_CONVERSION(signed long, unsigned int);
99 #endif
100 
101 #if PPL_CXX_PLAIN_CHAR_IS_SIGNED
102 PPL_SAFE_CONVERSION(signed long long, char);
103 #endif
104 PPL_SAFE_CONVERSION(signed long long, signed char);
105 PPL_SAFE_CONVERSION(signed long long, signed short);
106 PPL_SAFE_CONVERSION(signed long long, signed int);
107 PPL_SAFE_CONVERSION(signed long long, signed long);
108 #if PPL_SIZEOF_CHAR < PPL_SIZEOF_LONG_LONG
109 #if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
110 PPL_SAFE_CONVERSION(signed long long, char);
111 #endif
112 PPL_SAFE_CONVERSION(signed long long, unsigned char);
113 #endif
114 #if PPL_SIZEOF_SHORT < PPL_SIZEOF_LONG_LONG
115 PPL_SAFE_CONVERSION(signed long long, unsigned short);
116 #endif
117 #if PPL_SIZEOF_INT < PPL_SIZEOF_LONG_LONG
118 PPL_SAFE_CONVERSION(signed long long, unsigned int);
119 #endif
120 #if PPL_SIZEOF_LONG < PPL_SIZEOF_LONG_LONG
121 PPL_SAFE_CONVERSION(signed long long, unsigned long);
122 #endif
123 
124 #if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
125 PPL_SAFE_CONVERSION(unsigned short, char);
126 #endif
127 PPL_SAFE_CONVERSION(unsigned short, unsigned char);
128 
129 #if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
130 PPL_SAFE_CONVERSION(unsigned int, char);
131 #endif
132 PPL_SAFE_CONVERSION(unsigned int, unsigned char);
133 PPL_SAFE_CONVERSION(unsigned int, unsigned short);
134 
135 #if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
136 PPL_SAFE_CONVERSION(unsigned long, char);
137 #endif
138 PPL_SAFE_CONVERSION(unsigned long, unsigned char);
139 PPL_SAFE_CONVERSION(unsigned long, unsigned short);
140 PPL_SAFE_CONVERSION(unsigned long, unsigned int);
141 
142 #if !PPL_CXX_PLAIN_CHAR_IS_SIGNED
143 PPL_SAFE_CONVERSION(unsigned long long, char);
144 #endif
145 PPL_SAFE_CONVERSION(unsigned long long, unsigned char);
146 PPL_SAFE_CONVERSION(unsigned long long, unsigned short);
147 PPL_SAFE_CONVERSION(unsigned long long, unsigned int);
148 PPL_SAFE_CONVERSION(unsigned long long, unsigned long);
149 
150 
151 #if PPL_SIZEOF_CHAR <= PPL_SIZEOF_FLOAT - 2
152 PPL_SAFE_CONVERSION(float, char);
153 PPL_SAFE_CONVERSION(float, signed char);
154 PPL_SAFE_CONVERSION(float, unsigned char);
155 #endif
156 #if PPL_SIZEOF_SHORT <= PPL_SIZEOF_FLOAT - 2
157 PPL_SAFE_CONVERSION(float, signed short);
158 PPL_SAFE_CONVERSION(float, unsigned short);
159 #endif
160 #if PPL_SIZEOF_INT <= PPL_SIZEOF_FLOAT - 2
161 PPL_SAFE_CONVERSION(float, signed int);
162 PPL_SAFE_CONVERSION(float, unsigned int);
163 #endif
164 #if PPL_SIZEOF_LONG <= PPL_SIZEOF_FLOAT - 2
165 PPL_SAFE_CONVERSION(float, signed long);
166 PPL_SAFE_CONVERSION(float, unsigned long);
167 #endif
168 #if PPL_SIZEOF_LONG_LONG <= PPL_SIZEOF_FLOAT - 2
169 PPL_SAFE_CONVERSION(float, signed long long);
170 PPL_SAFE_CONVERSION(float, unsigned long long);
171 #endif
172 
173 #if PPL_SIZEOF_CHAR <= PPL_SIZEOF_DOUBLE - 4
174 PPL_SAFE_CONVERSION(double, char);
175 PPL_SAFE_CONVERSION(double, signed char);
176 PPL_SAFE_CONVERSION(double, unsigned char);
177 #endif
178 #if PPL_SIZEOF_SHORT <= PPL_SIZEOF_DOUBLE - 4
179 PPL_SAFE_CONVERSION(double, signed short);
180 PPL_SAFE_CONVERSION(double, unsigned short);
181 #endif
182 #if PPL_SIZEOF_INT <= PPL_SIZEOF_DOUBLE - 4
183 PPL_SAFE_CONVERSION(double, signed int);
184 PPL_SAFE_CONVERSION(double, unsigned int);
185 #endif
186 #if PPL_SIZEOF_LONG <= PPL_SIZEOF_DOUBLE - 4
187 PPL_SAFE_CONVERSION(double, signed long);
188 PPL_SAFE_CONVERSION(double, unsigned long);
189 #endif
190 #if PPL_SIZEOF_LONG_LONG <= PPL_SIZEOF_DOUBLE - 4
191 PPL_SAFE_CONVERSION(double, signed long long);
192 PPL_SAFE_CONVERSION(double, unsigned long long);
193 #endif
194 PPL_SAFE_CONVERSION(double, float);
195 
196 #if PPL_SIZEOF_CHAR <= PPL_SIZEOF_LONG_DOUBLE - 4
197 PPL_SAFE_CONVERSION(long double, char);
198 PPL_SAFE_CONVERSION(long double, signed char);
199 PPL_SAFE_CONVERSION(long double, unsigned char);
200 #endif
201 #if PPL_SIZEOF_SHORT <= PPL_SIZEOF_LONG_DOUBLE - 4
202 PPL_SAFE_CONVERSION(long double, signed short);
203 PPL_SAFE_CONVERSION(long double, unsigned short);
204 #endif
205 #if PPL_SIZEOF_INT <= PPL_SIZEOF_LONG_DOUBLE - 4
206 PPL_SAFE_CONVERSION(long double, signed int);
207 PPL_SAFE_CONVERSION(long double, unsigned int);
208 #endif
209 #if PPL_SIZEOF_LONG <= PPL_SIZEOF_LONG_DOUBLE - 4
210 PPL_SAFE_CONVERSION(long double, signed long);
211 PPL_SAFE_CONVERSION(long double, unsigned long);
212 #endif
213 #if PPL_SIZEOF_LONG_LONG <= PPL_SIZEOF_LONG_DOUBLE - 4
214 PPL_SAFE_CONVERSION(long double, signed long long);
215 PPL_SAFE_CONVERSION(long double, unsigned long long);
216 #endif
217 PPL_SAFE_CONVERSION(long double, float);
218 PPL_SAFE_CONVERSION(long double, double);
219 
220 PPL_SAFE_CONVERSION(mpz_class, char);
221 PPL_SAFE_CONVERSION(mpz_class, signed char);
222 PPL_SAFE_CONVERSION(mpz_class, signed short);
223 PPL_SAFE_CONVERSION(mpz_class, signed int);
224 PPL_SAFE_CONVERSION(mpz_class, signed long);
225 // GMP's API does not support signed long long.
226 PPL_SAFE_CONVERSION(mpz_class, unsigned char);
227 PPL_SAFE_CONVERSION(mpz_class, unsigned short);
228 PPL_SAFE_CONVERSION(mpz_class, unsigned int);
229 PPL_SAFE_CONVERSION(mpz_class, unsigned long);
230 // GMP's API does not support unsigned long long.
231 
232 PPL_SAFE_CONVERSION(mpq_class, char);
233 PPL_SAFE_CONVERSION(mpq_class, signed char);
234 PPL_SAFE_CONVERSION(mpq_class, signed short);
235 PPL_SAFE_CONVERSION(mpq_class, signed int);
236 PPL_SAFE_CONVERSION(mpq_class, signed long);
237 // GMP's API does not support signed long long.
238 PPL_SAFE_CONVERSION(mpq_class, unsigned char);
239 PPL_SAFE_CONVERSION(mpq_class, unsigned short);
240 PPL_SAFE_CONVERSION(mpq_class, unsigned int);
241 PPL_SAFE_CONVERSION(mpq_class, unsigned long);
242 // GMP's API does not support unsigned long long.
243 PPL_SAFE_CONVERSION(mpq_class, float);
244 PPL_SAFE_CONVERSION(mpq_class, double);
245 // GMP's API does not support long double.
246 
247 #undef PPL_SAFE_CONVERSION
248 
249 template <typename Policy, typename Type>
250 struct PPL_FUNCTION_CLASS(construct)<Policy, Policy, Type, Type> {
251  static inline Result function(Type& to, const Type& from, Rounding_Dir) {
252  new(&to) Type(from);
253  return V_EQ;
254  }
255 };
256 
257 template <typename To_Policy, typename From_Policy, typename To, typename From>
258 struct PPL_FUNCTION_CLASS(construct) {
259  static inline Result function(To& to, const From& from, Rounding_Dir dir) {
260  new(&to) To();
261  return assign<To_Policy, From_Policy>(to, from, dir);
262  }
263 };
264 
265 template <typename To_Policy, typename To>
266 struct PPL_FUNCTION_CLASS(construct_special) {
267  static inline Result function(To& to, Result_Class r, Rounding_Dir dir) {
268  new(&to) To();
269  return assign_special<To_Policy>(to, r, dir);
270  }
271 };
272 
273 template <typename To_Policy, typename From_Policy, typename To, typename From>
274 inline Result
275 assign_exact(To& to, const From& from, Rounding_Dir) {
276  to = from;
277  return V_EQ;
278 }
279 
280 template <typename To_Policy, typename From_Policy, typename Type>
281 inline typename Enable_If<Is_Same<To_Policy, From_Policy>::value, void>::type
282 copy_generic(Type& to, const Type& from) {
283  to = from;
284 }
285 
286 template <typename To_Policy, typename From_Policy, typename To, typename From>
287 inline Result
288 abs_generic(To& to, const From& from, Rounding_Dir dir) {
289  if (from < 0) {
290  return neg<To_Policy, From_Policy>(to, from, dir);
291  }
292  else {
293  return assign<To_Policy, From_Policy>(to, from, dir);
294  }
295 }
296 
297 template <typename To_Policy, typename From1_Policy, typename From2_Policy,
298  typename To, typename From>
299 inline void
300 gcd_exact_no_abs(To& to, const From& x, const From& y) {
301  To w_x = x;
302  To w_y = y;
303  To remainder;
304  while (w_y != 0) {
305  // The following is derived from the assumption that w_x % w_y
306  // is always representable. This is true for both native integers
307  // and IEC 559 floating point numbers.
308  rem<To_Policy, From1_Policy, From2_Policy>(remainder, w_x, w_y,
310  w_x = w_y;
311  w_y = remainder;
312  }
313  to = w_x;
314 }
315 
316 template <typename To_Policy, typename From1_Policy, typename From2_Policy,
317  typename To, typename From1, typename From2>
318 inline Result
319 gcd_exact(To& to, const From1& x, const From2& y, Rounding_Dir dir) {
320  gcd_exact_no_abs<To_Policy, From1_Policy, From2_Policy>(to, x, y);
321  return abs<To_Policy, To_Policy>(to, to, dir);
322 }
323 
324 template <typename To1_Policy, typename To2_Policy, typename To3_Policy,
325  typename From1_Policy, typename From2_Policy,
326  typename To1, typename To2, typename To3,
327  typename From1, typename From2>
328 inline Result
329 gcdext_exact(To1& to, To2& s, To3& t, const From1& x, const From2& y,
330  Rounding_Dir dir) {
331  // In case this becomes a bottleneck, we may consider using the
332  // Stehle'-Zimmermann algorithm (see R. Crandall and C. Pomerance,
333  // Prime Numbers - A Computational Perspective, Second Edition,
334  // Springer, 2005).
335  if (y == 0) {
336  if (x == 0) {
337  s = 0;
338  t = 1;
339  return V_EQ;
340  }
341  else {
342  if (x < 0) {
343  s = -1;
344  }
345  else {
346  s = 1;
347  }
348  t = 0;
349  return abs<To1_Policy, From1_Policy>(to, x, dir);
350  }
351  }
352 
353  s = 1;
354  t = 0;
355  bool negative_x = x < 0;
356  bool negative_y = y < 0;
357 
358  Result r;
359  r = abs<To1_Policy, From1_Policy>(to, x, dir);
360  if (r != V_EQ) {
361  return r;
362  }
363 
364  From2 a_y;
365  r = abs<To1_Policy, From2_Policy>(a_y, y, dir);
366  if (r != V_EQ) {
367  return r;
368  }
369 
370  // If PPL_MATCH_GMP_GCDEXT is defined then s is favored when the absolute
371  // values of the given numbers are equal. For instance if x and y
372  // are both 5 then s will be 1 and t will be 0, instead of the other
373  // way round. This is to match the behavior of GMP.
374 #define PPL_MATCH_GMP_GCDEXT 1
375 #ifdef PPL_MATCH_GMP_GCDEXT
376  if (to == a_y) {
377  goto sign_check;
378  }
379 #endif
380 
381  {
382  To2 v1 = 0;
383  To3 v2 = 1;
384  To1 v3 = static_cast<To1>(a_y);
385  while (true) {
386  To1 q = to / v3;
387  // Remainder, next candidate GCD.
388  To1 t3 = to - q*v3;
389  To2 t1 = s - static_cast<To2>(q)*v1;
390  To3 t2 = t - static_cast<To3>(q)*v2;
391  s = v1;
392  t = v2;
393  to = v3;
394  if (t3 == 0) {
395  break;
396  }
397  v1 = t1;
398  v2 = t2;
399  v3 = t3;
400  }
401  }
402 
403 #ifdef PPL_MATCH_GMP_GCDEXT
404  sign_check:
405 #endif
406  if (negative_x) {
407  r = neg<To2_Policy, To2_Policy>(s, s, dir);
408  if (r != V_EQ) {
409  return r;
410  }
411  }
412  if (negative_y) {
413  return neg<To3_Policy, To3_Policy>(t, t, dir);
414  }
415  return V_EQ;
416 #undef PPL_MATCH_GMP_GCDEXT
417 }
418 
419 template <typename To_Policy, typename From1_Policy, typename From2_Policy,
420  typename To, typename From1, typename From2>
421 inline Result
422 lcm_gcd_exact(To& to, const From1& x, const From2& y, Rounding_Dir dir) {
423  if (x == 0 || y == 0) {
424  to = 0;
425  return V_EQ;
426  }
427  To a_x;
428  To a_y;
429  Result r;
430  r = abs<From1_Policy, From1_Policy>(a_x, x, dir);
431  if (r != V_EQ) {
432  return r;
433  }
434  r = abs<From2_Policy, From2_Policy>(a_y, y, dir);
435  if (r != V_EQ) {
436  return r;
437  }
438  To gcd;
439  gcd_exact_no_abs<To_Policy, From1_Policy, From2_Policy>(gcd, a_x, a_y);
440  // The following is derived from the assumption that a_x / gcd(a_x, a_y)
441  // is always representable. This is true for both native integers
442  // and IEC 559 floating point numbers.
443  div<To_Policy, From1_Policy, To_Policy>(to, a_x, gcd, ROUND_NOT_NEEDED);
444  return mul<To_Policy, To_Policy, From2_Policy>(to, to, a_y, dir);
445 }
446 
447 template <typename Policy, typename Type>
448 inline Result_Relation
449 sgn_generic(const Type& x) {
450  if (x > 0) {
451  return VR_GT;
452  }
453  if (x == 0) {
454  return VR_EQ;
455  }
456  return VR_LT;
457 }
458 
459 template <typename T1, typename T2, typename Enable = void>
460 struct Safe_Int_Comparison : public False {
461 };
462 
463 template <typename T1, typename T2>
464 struct Safe_Int_Comparison<T1, T2, typename Enable_If<(C_Integer<T1>::value && C_Integer<T2>::value)>::type>
465  : public Bool<(C_Integer<T1>::is_signed
466  ? (C_Integer<T2>::is_signed
467  || sizeof(T2) < sizeof(T1)
468  || sizeof(T2) < sizeof(int))
469  : (!C_Integer<T2>::is_signed
470  || sizeof(T1) < sizeof(T2)
471  || sizeof(T1) < sizeof(int)))> {
472 };
473 
474 
475 template <typename T1, typename T2>
476 inline typename Enable_If<(Safe_Int_Comparison<T1, T2>::value
477  || Safe_Conversion<T1, T2>::value
478  || Safe_Conversion<T2, T1>::value), bool>::type
479 lt(const T1& x, const T2& y) {
480  return x < y;
481 }
482 template <typename T1, typename T2>
483 inline typename Enable_If<(Safe_Int_Comparison<T1, T2>::value
484  || Safe_Conversion<T1, T2>::value
485  || Safe_Conversion<T2, T1>::value), bool>::type
486 le(const T1& x, const T2& y) {
487  return x <= y;
488 }
489 template <typename T1, typename T2>
490 inline typename Enable_If<(Safe_Int_Comparison<T1, T2>::value
491  || Safe_Conversion<T1, T2>::value
492  || Safe_Conversion<T2, T1>::value), bool>::type
493 eq(const T1& x, const T2& y) {
494  return x == y;
495 }
496 
497 template <typename S, typename U>
498 inline typename Enable_If<(!Safe_Int_Comparison<S, U>::value
499  && C_Integer<U>::value
500  && C_Integer<S>::is_signed), bool>::type
501 lt(const S& x, const U& y) {
502  return x < 0 || static_cast<typename C_Integer<S>::other_type>(x) < y;
503 }
504 
505 template <typename U, typename S>
506 inline typename Enable_If<(!Safe_Int_Comparison<S, U>::value
507  && C_Integer<U>::value
508  && C_Integer<S>::is_signed), bool>::type
509 lt(const U& x, const S& y) {
510  return y >= 0 && x < static_cast<typename C_Integer<S>::other_type>(y);
511 }
512 
513 template <typename S, typename U>
514 inline typename Enable_If<(!Safe_Int_Comparison<S, U>::value
515  && C_Integer<U>::value
516  && C_Integer<S>::is_signed), bool>::type
517 le(const S& x, const U& y) {
518  return x < 0 || static_cast<typename C_Integer<S>::other_type>(x) <= y;
519 }
520 
521 template <typename U, typename S>
522 inline typename Enable_If<(!Safe_Int_Comparison<S, U>::value
523  && C_Integer<U>::value
524  && C_Integer<S>::is_signed), bool>::type
525 le(const U& x, const S& y) {
526  return y >= 0 && x <= static_cast<typename C_Integer<S>::other_type>(y);
527 }
528 
529 template <typename S, typename U>
530 inline typename Enable_If<(!Safe_Int_Comparison<S, U>::value
531  && C_Integer<U>::value
532  && C_Integer<S>::is_signed), bool>::type
533 eq(const S& x, const U& y) {
534  return x >= 0 && static_cast<typename C_Integer<S>::other_type>(x) == y;
535 }
536 
537 template <typename U, typename S>
538 inline typename Enable_If<(!Safe_Int_Comparison<S, U>::value
539  && C_Integer<U>::value
540  && C_Integer<S>::is_signed), bool>::type
541 eq(const U& x, const S& y) {
542  return y >= 0 && x == static_cast<typename C_Integer<S>::other_type>(y);
543 }
544 
545 template <typename T1, typename T2>
546 inline typename Enable_If<(!Safe_Conversion<T1, T2>::value
547  && !Safe_Conversion<T2, T1>::value
548  && (!C_Integer<T1>::value || !C_Integer<T2>::value)), bool>::type
549 eq(const T1& x, const T2& y) {
550  PPL_DIRTY_TEMP(T1, tmp);
551  Result r = assign_r(tmp, y, ROUND_CHECK);
552  // FIXME: We can do this also without fpu inexact check using a
553  // conversion back and forth and then testing equality. We should
554  // code this in checked_float_inlines.hh, probably it's faster also
555  // if fpu supports inexact check.
556  PPL_ASSERT(r != V_LE && r != V_GE && r != V_LGE);
557  return r == V_EQ && x == tmp;
558 }
559 
560 template <typename T1, typename T2>
561 inline typename Enable_If<(!Safe_Conversion<T1, T2>::value
562  && !Safe_Conversion<T2, T1>::value
563  && (!C_Integer<T1>::value || !C_Integer<T2>::value)), bool>::type
564 lt(const T1& x, const T2& y) {
565  PPL_DIRTY_TEMP(T1, tmp);
566  Result r = assign_r(tmp, y, ROUND_UP);
567  if (!result_representable(r)) {
568  return true;
569  }
570  switch (result_relation(r)) {
571  case VR_EQ:
572  case VR_LT:
573  case VR_LE:
574  return x < tmp;
575  default:
576  return false;
577  }
578 }
579 
580 template <typename T1, typename T2>
581 inline typename
582 Enable_If<(!Safe_Conversion<T1, T2>::value
583  && !Safe_Conversion<T2, T1>::value
584  && (!C_Integer<T1>::value || !C_Integer<T2>::value)), bool>::type
585 le(const T1& x, const T2& y) {
586  PPL_DIRTY_TEMP(T1, tmp);
587  Result r = assign_r(tmp, y, (ROUND_UP | ROUND_STRICT_RELATION));
588  // FIXME: We can do this also without fpu inexact check using a
589  // conversion back and forth and then testing equality. We should
590  // code this in checked_float_inlines.hh, probably it's faster also
591  // if fpu supports inexact check.
592  PPL_ASSERT(r != V_LE && r != V_GE && r != V_LGE);
593  if (!result_representable(r)) {
594  return true;
595  }
596  switch (result_relation(r)) {
597  case VR_EQ:
598  return x <= tmp;
599  case VR_LT:
600  return x < tmp;
601  case VR_LE:
602  case VR_GE:
603  case VR_LGE:
604  // See comment above.
605  PPL_UNREACHABLE;
606  return false;
607  default:
608  return false;
609  }
610 }
611 
612 template <typename Policy1, typename Policy2,
613  typename Type1, typename Type2>
614 inline bool
615 lt_p(const Type1& x, const Type2& y) {
616  return lt(x, y);
617 }
618 
619 template <typename Policy1, typename Policy2,
620  typename Type1, typename Type2>
621 inline bool
622 le_p(const Type1& x, const Type2& y) {
623  return le(x, y);
624 }
625 
626 template <typename Policy1, typename Policy2,
627  typename Type1, typename Type2>
628 inline bool
629 eq_p(const Type1& x, const Type2& y) {
630  return eq(x, y);
631 }
632 
633 template <typename Policy1, typename Policy2,
634  typename Type1, typename Type2>
635 inline Result_Relation
636 cmp_generic(const Type1& x, const Type2& y) {
637  if (lt(y, x)) {
638  return VR_GT;
639  }
640  if (lt(x, y)) {
641  return VR_LT;
642  }
643  return VR_EQ;
644 }
645 
646 template <typename Policy, typename Type>
647 inline Result
648 assign_nan(Type& to, Result r) {
649  assign_special<Policy>(to, VC_NAN, ROUND_IGNORE);
650  return r;
651 }
652 
653 template <typename Policy, typename Type>
654 inline Result
655 input_generic(Type& to, std::istream& is, Rounding_Dir dir) {
656  PPL_DIRTY_TEMP(mpq_class, q);
657  Result r = input_mpq(q, is);
658  Result_Class c = result_class(r);
659  switch (c) {
660  case VC_MINUS_INFINITY:
661  case VC_PLUS_INFINITY:
662  return assign_special<Policy>(to, c, dir);
663  case VC_NAN:
664  return assign_nan<Policy>(to, r);
665  default:
666  break;
667  }
668  PPL_ASSERT(r == V_EQ);
669  return assign<Policy, void>(to, q, dir);
670 }
671 
672 } // namespace Checked
673 
674 } // namespace Parma_Polyhedra_Library
675 
676 #endif // !defined(PPL_checked_inlines_hh)
The computed result is exact.
Definition: Result_defs.hh:81
PPL_SAFE_CONVERSION(signed short, signed char)
Rounding_Dir
Rounding directions for arithmetic computations.
Result
Possible outcomes of a checked arithmetic computation.
Definition: Result_defs.hh:76
From bool Type Type Rounding_Dir To
Result gcdext_exact(To1 &to, To2 &s, To3 &t, const From1 &x, const From2 &y, Rounding_Dir dir)
From bool Type Type Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir unsigned Rounding_Dir unsigned Rounding_Dir unsigned Rounding_Dir Rounding_Dir To2
A class holding a constant called value that evaluates to true.
Equal. This need to be accompanied by a value.
Definition: Result_defs.hh:51
Less than. This need to be accompanied by a value.
Definition: Result_defs.hh:54
From bool Type Type Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir unsigned Rounding_Dir unsigned Rounding_Dir unsigned Rounding_Dir Rounding_Dir To1
Result gcd_exact(To &to, const From1 &x, const From2 &y, Rounding_Dir dir)
Coefficient value
Definition: PIP_Tree.cc:618
void gcd_exact_no_abs(To &to, const From &x, const From &y)
From bool Type Type Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir From1
Result assign_exact(To &to, const From &from, Rounding_Dir)
The entire library is confined to this namespace.
Definition: version.hh:61
Greater than. This need to be accompanied by a value.
Definition: Result_defs.hh:57
Enable_If< Is_Same< To_Policy, From_Policy >::value, void >::type copy_generic(Type &to, const Type &from)
Result_Relation sgn_generic(const Type &x)
From bool Type Type Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir From2
From bool Type Type Rounding_Dir From
Result lcm_gcd_exact(To &to, const From1 &x, const From2 &y, Rounding_Dir dir)
Result abs_generic(To &to, const From &from, Rounding_Dir dir)
A class that provides a type member called type equivalent to T if and only if b is true...
A class holding a constant called value that evaluates to false.
From bool Type Type Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir unsigned Rounding_Dir unsigned Rounding_Dir unsigned Rounding_Dir Rounding_Dir To3
A class holding a constant called value that evaluates to b.