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 
32 /*! \brief
33   Performs the test <CODE>a < b</CODE> avoiding the warning about the
34   comparison being always false due to limited range of data type.
35   FIXME: we have not found a working solution. The GCC option
36   -Wno-type-limits suppresses the warning
37 */
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>
PPL_FUNCTION_CLASS(construct)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>
PPL_FUNCTION_CLASS(construct)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>
PPL_FUNCTION_CLASS(construct_special)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
assign_exact(To & to,const From & from,Rounding_Dir)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
copy_generic(Type & to,const Type & from)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
abs_generic(To & to,const From & from,Rounding_Dir dir)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
gcd_exact_no_abs(To & to,const From & x,const From & y)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,
309                                                ROUND_NOT_NEEDED);
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
gcd_exact(To & to,const From1 & x,const From2 & y,Rounding_Dir dir)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
gcdext_exact(To1 & to,To2 & s,To3 & t,const From1 & x,const From2 & y,Rounding_Dir dir)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
lcm_gcd_exact(To & to,const From1 & x,const From2 & y,Rounding_Dir dir)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
sgn_generic(const Type & x)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
lt(const T1 & x,const T2 & y)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
le(const T1 & x,const T2 & y)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
eq(const T1 & x,const T2 & y)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
lt(const S & x,const U & y)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
lt(const U & x,const S & y)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
le(const S & x,const U & y)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
le(const U & x,const S & y)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
eq(const S & x,const U & y)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
eq(const U & x,const S & y)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
eq(const T1 & x,const T2 & y)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
lt(const T1 & x,const T2 & y)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
le(const T1 & x,const T2 & y)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
lt_p(const Type1 & x,const Type2 & y)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
le_p(const Type1 & x,const Type2 & y)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
eq_p(const Type1 & x,const Type2 & y)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
cmp_generic(const Type1 & x,const Type2 & y)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
assign_nan(Type & to,Result r)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
input_generic(Type & to,std::istream & is,Rounding_Dir dir)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)
677