1 /* Specialized "checked" functions for GMP's mpq_class numbers.
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_mpq_inlines_hh
25 #define PPL_checked_mpq_inlines_hh 1
26 
27 #include <sstream>
28 #include <climits>
29 #include <stdexcept>
30 
31 namespace Parma_Polyhedra_Library {
32 
33 namespace Checked {
34 
35 template <typename Policy>
36 inline Result
classify_mpq(const mpq_class & v,bool nan,bool inf,bool sign)37 classify_mpq(const mpq_class& v, bool nan, bool inf, bool sign) {
38   if ((Policy::has_nan || Policy::has_infinity)
39       && ::sgn(v.get_den()) == 0) {
40     int s = ::sgn(v.get_num());
41     if (Policy::has_nan && (nan || sign) && s == 0) {
42       return V_NAN;
43     }
44     if (!inf && !sign) {
45       return V_LGE;
46     }
47     if (Policy::has_infinity) {
48       if (s < 0) {
49         return inf ? V_EQ_MINUS_INFINITY : V_LT;
50       }
51       if (s > 0) {
52         return inf ? V_EQ_PLUS_INFINITY : V_GT;
53       }
54     }
55   }
56   if (sign) {
57     return static_cast<Result>(sgn<Policy>(v));
58   }
59   return V_LGE;
60 }
61 
PPL_SPECIALIZE_CLASSIFY(classify_mpq,mpq_class)62 PPL_SPECIALIZE_CLASSIFY(classify_mpq, mpq_class)
63 
64 template <typename Policy>
65 inline bool
66 is_nan_mpq(const mpq_class& v) {
67   return Policy::has_nan
68     && ::sgn(v.get_den()) == 0
69     && ::sgn(v.get_num()) == 0;
70 }
71 
PPL_SPECIALIZE_IS_NAN(is_nan_mpq,mpq_class)72 PPL_SPECIALIZE_IS_NAN(is_nan_mpq, mpq_class)
73 
74 template <typename Policy>
75 inline bool
76 is_minf_mpq(const mpq_class& v) {
77   return Policy::has_infinity
78     && ::sgn(v.get_den()) == 0
79     && ::sgn(v.get_num()) < 0;
80 }
81 
PPL_SPECIALIZE_IS_MINF(is_minf_mpq,mpq_class)82 PPL_SPECIALIZE_IS_MINF(is_minf_mpq, mpq_class)
83 
84 template <typename Policy>
85 inline bool
86 is_pinf_mpq(const mpq_class& v) {
87   return Policy::has_infinity
88     && ::sgn(v.get_den()) == 0
89     && ::sgn(v.get_num()) > 0;
90 }
91 
PPL_SPECIALIZE_IS_PINF(is_pinf_mpq,mpq_class)92 PPL_SPECIALIZE_IS_PINF(is_pinf_mpq, mpq_class)
93 
94 template <typename Policy>
95 inline bool
96 is_int_mpq(const mpq_class& v) {
97   if ((Policy::has_infinity || Policy::has_nan)
98       && ::sgn(v.get_den()) == 0) {
99     return !(Policy::has_nan && ::sgn(v.get_num()) == 0);
100   }
101   else {
102     return v.get_den() == 1;
103   }
104 }
105 
PPL_SPECIALIZE_IS_INT(is_int_mpq,mpq_class)106 PPL_SPECIALIZE_IS_INT(is_int_mpq, mpq_class)
107 
108 template <typename Policy>
109 inline Result
110 assign_special_mpq(mpq_class& v, Result_Class c, Rounding_Dir) {
111   switch (c) {
112   case VC_NAN:
113     if (Policy::has_nan) {
114       v.get_num() = 0;
115       v.get_den() = 0;
116       return V_NAN | V_UNREPRESENTABLE;
117     }
118     return V_NAN;
119   case VC_MINUS_INFINITY:
120     if (Policy::has_infinity) {
121       v.get_num() = -1;
122       v.get_den() = 0;
123       return V_EQ_MINUS_INFINITY;
124     }
125     return V_EQ_MINUS_INFINITY | V_UNREPRESENTABLE;
126   case VC_PLUS_INFINITY:
127     if (Policy::has_infinity) {
128       v.get_num() = 1;
129       v.get_den() = 0;
130       return V_EQ_PLUS_INFINITY;
131     }
132     return V_EQ_PLUS_INFINITY | V_UNREPRESENTABLE;
133   default:
134     PPL_UNREACHABLE;
135     return V_NAN | V_UNREPRESENTABLE;
136   }
137 }
138 
PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_mpq,mpq_class)139 PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_mpq, mpq_class)
140 
141 PPL_SPECIALIZE_COPY(copy_generic, mpq_class)
142 
143 template <typename To_Policy, typename From_Policy, typename From>
144 inline Result
145 construct_mpq_base(mpq_class& to, const From& from, Rounding_Dir) {
146   new(&to) mpq_class(from);
147   return V_EQ;
148 }
149 
PPL_SPECIALIZE_CONSTRUCT(construct_mpq_base,mpq_class,mpz_class)150 PPL_SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, mpz_class)
151 PPL_SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, char)
152 PPL_SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, signed char)
153 PPL_SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, signed short)
154 PPL_SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, signed int)
155 PPL_SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, signed long)
156 PPL_SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, unsigned char)
157 PPL_SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, unsigned short)
158 PPL_SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, unsigned int)
159 PPL_SPECIALIZE_CONSTRUCT(construct_mpq_base, mpq_class, unsigned long)
160 
161 template <typename To_Policy, typename From_Policy, typename From>
162 inline Result
163 construct_mpq_float(mpq_class& to, const From& from, Rounding_Dir dir) {
164   if (is_nan<From_Policy>(from)) {
165     return construct_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
166   }
167   else if (is_minf<From_Policy>(from)) {
168     return construct_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
169   }
170   else if (is_pinf<From_Policy>(from)) {
171     return construct_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
172   }
173   new(&to) mpq_class(from);
174   return V_EQ;
175 }
176 
PPL_SPECIALIZE_CONSTRUCT(construct_mpq_float,mpq_class,float)177 PPL_SPECIALIZE_CONSTRUCT(construct_mpq_float, mpq_class, float)
178 PPL_SPECIALIZE_CONSTRUCT(construct_mpq_float, mpq_class, double)
179 
180 PPL_SPECIALIZE_ASSIGN(assign_exact, mpq_class, mpq_class)
181 PPL_SPECIALIZE_ASSIGN(assign_exact, mpq_class, mpz_class)
182 PPL_SPECIALIZE_ASSIGN(assign_exact, mpq_class, char)
183 PPL_SPECIALIZE_ASSIGN(assign_exact, mpq_class, signed char)
184 PPL_SPECIALIZE_ASSIGN(assign_exact, mpq_class, signed short)
185 PPL_SPECIALIZE_ASSIGN(assign_exact, mpq_class, signed int)
186 PPL_SPECIALIZE_ASSIGN(assign_exact, mpq_class, signed long)
187 PPL_SPECIALIZE_ASSIGN(assign_exact, mpq_class, unsigned char)
188 PPL_SPECIALIZE_ASSIGN(assign_exact, mpq_class, unsigned short)
189 PPL_SPECIALIZE_ASSIGN(assign_exact, mpq_class, unsigned int)
190 PPL_SPECIALIZE_ASSIGN(assign_exact, mpq_class, unsigned long)
191 
192 template <typename To_Policy, typename From_Policy, typename From>
193 inline Result
194 assign_mpq_float(mpq_class& to, const From& from, Rounding_Dir dir) {
195   if (is_nan<From_Policy>(from)) {
196     return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
197   }
198   else if (is_minf<From_Policy>(from)) {
199     return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
200   }
201   else if (is_pinf<From_Policy>(from)) {
202     return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
203   }
204   assign_mpq_numeric_float(to, from);
205   return V_EQ;
206 }
207 
PPL_SPECIALIZE_ASSIGN(assign_mpq_float,mpq_class,float)208 PPL_SPECIALIZE_ASSIGN(assign_mpq_float, mpq_class, float)
209 PPL_SPECIALIZE_ASSIGN(assign_mpq_float, mpq_class, double)
210 PPL_SPECIALIZE_ASSIGN(assign_mpq_float, mpq_class, long double)
211 
212 template <typename To_Policy, typename From_Policy, typename From>
213 inline Result
214 assign_mpq_signed_int(mpq_class& to, const From from, Rounding_Dir) {
215   if (sizeof(From) <= sizeof(signed long)) {
216     to = static_cast<signed long>(from);
217   }
218   else {
219     mpz_ptr m = to.get_num().get_mpz_t();
220     if (from >= 0) {
221       mpz_import(m, 1, 1, sizeof(From), 0, 0, &from);
222     }
223     else {
224       From n = -from;
225       mpz_import(m, 1, 1, sizeof(From), 0, 0, &n);
226       mpz_neg(m, m);
227     }
228     to.get_den() = 1;
229   }
230   return V_EQ;
231 }
232 
PPL_SPECIALIZE_ASSIGN(assign_mpq_signed_int,mpq_class,signed long long)233 PPL_SPECIALIZE_ASSIGN(assign_mpq_signed_int, mpq_class, signed long long)
234 
235 template <typename To_Policy, typename From_Policy, typename From>
236 inline Result
237 assign_mpq_unsigned_int(mpq_class& to, const From from, Rounding_Dir) {
238   if (sizeof(From) <= sizeof(unsigned long)) {
239     to = static_cast<unsigned long>(from);
240   }
241   else {
242     mpz_import(to.get_num().get_mpz_t(), 1, 1, sizeof(From), 0, 0, &from);
243     to.get_den() = 1;
244   }
245   return V_EQ;
246 }
247 
PPL_SPECIALIZE_ASSIGN(assign_mpq_unsigned_int,mpq_class,unsigned long long)248 PPL_SPECIALIZE_ASSIGN(assign_mpq_unsigned_int, mpq_class, unsigned long long)
249 
250 template <typename To_Policy, typename From_Policy>
251 inline Result
252 floor_mpq(mpq_class& to, const mpq_class& from, Rounding_Dir) {
253   mpz_fdiv_q(to.get_num().get_mpz_t(),
254              from.get_num().get_mpz_t(), from.get_den().get_mpz_t());
255   to.get_den() = 1;
256   return V_EQ;
257 }
258 
PPL_SPECIALIZE_FLOOR(floor_mpq,mpq_class,mpq_class)259 PPL_SPECIALIZE_FLOOR(floor_mpq, mpq_class, mpq_class)
260 
261 template <typename To_Policy, typename From_Policy>
262 inline Result
263 ceil_mpq(mpq_class& to, const mpq_class& from, Rounding_Dir) {
264   mpz_cdiv_q(to.get_num().get_mpz_t(),
265              from.get_num().get_mpz_t(), from.get_den().get_mpz_t());
266   to.get_den() = 1;
267   return V_EQ;
268 }
269 
PPL_SPECIALIZE_CEIL(ceil_mpq,mpq_class,mpq_class)270 PPL_SPECIALIZE_CEIL(ceil_mpq, mpq_class, mpq_class)
271 
272 template <typename To_Policy, typename From_Policy>
273 inline Result
274 trunc_mpq(mpq_class& to, const mpq_class& from, Rounding_Dir) {
275   mpz_tdiv_q(to.get_num().get_mpz_t(),
276              from.get_num().get_mpz_t(), from.get_den().get_mpz_t());
277   to.get_den() = 1;
278   return V_EQ;
279 }
280 
PPL_SPECIALIZE_TRUNC(trunc_mpq,mpq_class,mpq_class)281 PPL_SPECIALIZE_TRUNC(trunc_mpq, mpq_class, mpq_class)
282 
283 template <typename To_Policy, typename From_Policy>
284 inline Result
285 neg_mpq(mpq_class& to, const mpq_class& from, Rounding_Dir) {
286   mpq_neg(to.get_mpq_t(), from.get_mpq_t());
287   return V_EQ;
288 }
289 
PPL_SPECIALIZE_NEG(neg_mpq,mpq_class,mpq_class)290 PPL_SPECIALIZE_NEG(neg_mpq, mpq_class, mpq_class)
291 
292 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
293 inline Result
294 add_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y, Rounding_Dir) {
295   to = x + y;
296   return V_EQ;
297 }
298 
PPL_SPECIALIZE_ADD(add_mpq,mpq_class,mpq_class,mpq_class)299 PPL_SPECIALIZE_ADD(add_mpq, mpq_class, mpq_class, mpq_class)
300 
301 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
302 inline Result
303 sub_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y, Rounding_Dir) {
304   to = x - y;
305   return V_EQ;
306 }
307 
PPL_SPECIALIZE_SUB(sub_mpq,mpq_class,mpq_class,mpq_class)308 PPL_SPECIALIZE_SUB(sub_mpq, mpq_class, mpq_class, mpq_class)
309 
310 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
311 inline Result
312 mul_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y, Rounding_Dir) {
313   to = x * y;
314   return V_EQ;
315 }
316 
PPL_SPECIALIZE_MUL(mul_mpq,mpq_class,mpq_class,mpq_class)317 PPL_SPECIALIZE_MUL(mul_mpq, mpq_class, mpq_class, mpq_class)
318 
319 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
320 inline Result
321 div_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y, Rounding_Dir) {
322   if (CHECK_P(To_Policy::check_div_zero, sgn(y) == 0)) {
323     return assign_nan<To_Policy>(to, V_DIV_ZERO);
324   }
325   to = x / y;
326   return V_EQ;
327 }
328 
PPL_SPECIALIZE_DIV(div_mpq,mpq_class,mpq_class,mpq_class)329 PPL_SPECIALIZE_DIV(div_mpq, mpq_class, mpq_class, mpq_class)
330 
331 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
332 inline Result
333 idiv_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y, Rounding_Dir dir) {
334   if (CHECK_P(To_Policy::check_div_zero, sgn(y) == 0)) {
335     return assign_nan<To_Policy>(to, V_DIV_ZERO);
336   }
337   to = x / y;
338   return trunc<To_Policy, To_Policy>(to, to, dir);
339 }
340 
PPL_SPECIALIZE_IDIV(idiv_mpq,mpq_class,mpq_class,mpq_class)341 PPL_SPECIALIZE_IDIV(idiv_mpq, mpq_class, mpq_class, mpq_class)
342 
343 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
344 inline Result
345 rem_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y, Rounding_Dir) {
346   if (CHECK_P(To_Policy::check_div_zero, sgn(y) == 0)) {
347     return assign_nan<To_Policy>(to, V_MOD_ZERO);
348   }
349   PPL_DIRTY_TEMP(mpq_class, tmp);
350   tmp = x / y;
351   tmp.get_num() %= tmp.get_den();
352   to = tmp * y;
353   return V_EQ;
354 }
355 
PPL_SPECIALIZE_REM(rem_mpq,mpq_class,mpq_class,mpq_class)356 PPL_SPECIALIZE_REM(rem_mpq, mpq_class, mpq_class, mpq_class)
357 
358 template <typename To_Policy, typename From_Policy>
359 inline Result
360 add_2exp_mpq(mpq_class& to, const mpq_class& x, unsigned int exp,
361              Rounding_Dir) {
362   PPL_DIRTY_TEMP(mpz_class, v);
363   v = 1;
364   mpz_mul_2exp(v.get_mpz_t(), v.get_mpz_t(), exp);
365   to = x + v;
366   return V_EQ;
367 }
368 
PPL_SPECIALIZE_ADD_2EXP(add_2exp_mpq,mpq_class,mpq_class)369 PPL_SPECIALIZE_ADD_2EXP(add_2exp_mpq, mpq_class, mpq_class)
370 
371 template <typename To_Policy, typename From_Policy>
372 inline Result
373 sub_2exp_mpq(mpq_class& to, const mpq_class& x, unsigned int exp,
374              Rounding_Dir) {
375   PPL_DIRTY_TEMP(mpz_class, v);
376   v = 1;
377   mpz_mul_2exp(v.get_mpz_t(), v.get_mpz_t(), exp);
378   to = x - v;
379   return V_EQ;
380 }
381 
PPL_SPECIALIZE_SUB_2EXP(sub_2exp_mpq,mpq_class,mpq_class)382 PPL_SPECIALIZE_SUB_2EXP(sub_2exp_mpq, mpq_class, mpq_class)
383 
384 template <typename To_Policy, typename From_Policy>
385 inline Result
386 mul_2exp_mpq(mpq_class& to, const mpq_class& x, unsigned int exp,
387              Rounding_Dir) {
388   mpz_mul_2exp(to.get_num().get_mpz_t(), x.get_num().get_mpz_t(), exp);
389   to.get_den() = x.get_den();
390   to.canonicalize();
391   return V_EQ;
392 }
393 
PPL_SPECIALIZE_MUL_2EXP(mul_2exp_mpq,mpq_class,mpq_class)394 PPL_SPECIALIZE_MUL_2EXP(mul_2exp_mpq, mpq_class, mpq_class)
395 
396 template <typename To_Policy, typename From_Policy>
397 inline Result
398 div_2exp_mpq(mpq_class& to, const mpq_class& x, unsigned int exp,
399              Rounding_Dir) {
400   to.get_num() = x.get_num();
401   mpz_mul_2exp(to.get_den().get_mpz_t(), x.get_den().get_mpz_t(), exp);
402   to.canonicalize();
403   return V_EQ;
404 }
405 
PPL_SPECIALIZE_DIV_2EXP(div_2exp_mpq,mpq_class,mpq_class)406 PPL_SPECIALIZE_DIV_2EXP(div_2exp_mpq, mpq_class, mpq_class)
407 
408 template <typename To_Policy, typename From_Policy>
409 inline Result
410 smod_2exp_mpq(mpq_class& to, const mpq_class& x, unsigned int exp,
411               Rounding_Dir) {
412   mpz_mul_2exp(to.get_den().get_mpz_t(), x.get_den().get_mpz_t(), exp);
413   mpz_fdiv_r(to.get_num().get_mpz_t(), x.get_num().get_mpz_t(), to.get_den().get_mpz_t());
414   mpz_fdiv_q_2exp(to.get_den().get_mpz_t(), to.get_den().get_mpz_t(), 1);
415   bool neg = to.get_num() >= to.get_den();
416   mpz_mul_2exp(to.get_den().get_mpz_t(), to.get_den().get_mpz_t(), 1);
417   if (neg) {
418     to.get_num() -= to.get_den();
419   }
420   mpz_mul_2exp(to.get_num().get_mpz_t(), to.get_num().get_mpz_t(), exp);
421   to.canonicalize();
422   return V_EQ;
423 }
424 
PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_mpq,mpq_class,mpq_class)425 PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_mpq, mpq_class, mpq_class)
426 
427 template <typename To_Policy, typename From_Policy>
428 inline Result
429 umod_2exp_mpq(mpq_class& to, const mpq_class& x, unsigned int exp,
430               Rounding_Dir) {
431   mpz_mul_2exp(to.get_den().get_mpz_t(), x.get_den().get_mpz_t(), exp);
432   mpz_fdiv_r(to.get_num().get_mpz_t(), x.get_num().get_mpz_t(), to.get_den().get_mpz_t());
433   mpz_mul_2exp(to.get_num().get_mpz_t(), to.get_num().get_mpz_t(), exp);
434   to.canonicalize();
435   return V_EQ;
436 }
437 
PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_mpq,mpq_class,mpq_class)438 PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_mpq, mpq_class, mpq_class)
439 
440 template <typename To_Policy, typename From_Policy>
441 inline Result
442 abs_mpq(mpq_class& to, const mpq_class& from, Rounding_Dir) {
443   to = abs(from);
444   return V_EQ;
445 }
446 
PPL_SPECIALIZE_ABS(abs_mpq,mpq_class,mpq_class)447 PPL_SPECIALIZE_ABS(abs_mpq, mpq_class, mpq_class)
448 
449 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
450 inline Result
451 add_mul_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y,
452             Rounding_Dir) {
453   to += x * y;
454   return V_EQ;
455 }
456 
PPL_SPECIALIZE_ADD_MUL(add_mul_mpq,mpq_class,mpq_class,mpq_class)457 PPL_SPECIALIZE_ADD_MUL(add_mul_mpq, mpq_class, mpq_class, mpq_class)
458 
459 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
460 inline Result
461 sub_mul_mpq(mpq_class& to, const mpq_class& x, const mpq_class& y,
462             Rounding_Dir) {
463   to -= x * y;
464   return V_EQ;
465 }
466 
467 PPL_SPECIALIZE_SUB_MUL(sub_mul_mpq, mpq_class, mpq_class, mpq_class)
468 
469 extern unsigned irrational_precision;
470 
471 template <typename To_Policy, typename From_Policy>
472 inline Result
sqrt_mpq(mpq_class & to,const mpq_class & from,Rounding_Dir dir)473 sqrt_mpq(mpq_class& to, const mpq_class& from, Rounding_Dir dir) {
474   if (CHECK_P(To_Policy::check_sqrt_neg, from < 0)) {
475     return assign_nan<To_Policy>(to, V_SQRT_NEG);
476   }
477   if (from == 0) {
478     to = 0;
479     return V_EQ;
480   }
481   bool gt1 = from.get_num() > from.get_den();
482   const mpz_class& from_a = gt1 ? from.get_num() : from.get_den();
483   const mpz_class& from_b = gt1 ? from.get_den() : from.get_num();
484   mpz_class& to_a = gt1 ? to.get_num() : to.get_den();
485   mpz_class& to_b = gt1 ? to.get_den() : to.get_num();
486   Rounding_Dir rdir = gt1 ? dir : inverse(dir);
487   mul_2exp<To_Policy, From_Policy>(to_a, from_a,
488                                    2*irrational_precision, ROUND_IGNORE);
489   Result r_div
490     = div<To_Policy, To_Policy, To_Policy>(to_a, to_a, from_b, rdir);
491   Result r_sqrt = sqrt<To_Policy, To_Policy>(to_a, to_a, rdir);
492   to_b = 1;
493   mul_2exp<To_Policy, To_Policy>(to_b, to_b,
494                                  irrational_precision, ROUND_IGNORE);
495   to.canonicalize();
496   return (r_div != V_EQ) ? r_div : r_sqrt;
497 }
498 
PPL_SPECIALIZE_SQRT(sqrt_mpq,mpq_class,mpq_class)499 PPL_SPECIALIZE_SQRT(sqrt_mpq, mpq_class, mpq_class)
500 
501 template <typename Policy>
502 inline Result
503 input_mpq(mpq_class& to, std::istream& is, Rounding_Dir dir) {
504   Result r = input_mpq(to, is);
505   Result_Class c = result_class(r);
506   switch (c) {
507   case VC_MINUS_INFINITY:
508   case VC_PLUS_INFINITY:
509     return assign_special<Policy>(to, c, dir);
510   case VC_NAN:
511     return assign_nan<Policy>(to, r);
512   default:
513     return r;
514   }
515 }
516 
PPL_SPECIALIZE_INPUT(input_mpq,mpq_class)517 PPL_SPECIALIZE_INPUT(input_mpq, mpq_class)
518 
519 template <typename Policy>
520 inline Result
521 output_mpq(std::ostream& os,
522            const mpq_class& from,
523            const Numeric_Format&,
524            Rounding_Dir) {
525   os << from;
526   return V_EQ;
527 }
528 
529 PPL_SPECIALIZE_OUTPUT(output_mpq, mpq_class)
530 
531 } // namespace Checked
532 
533 //! Returns the precision parameter used for irrational calculations.
534 inline unsigned
irrational_precision()535 irrational_precision() {
536   return Checked::irrational_precision;
537 }
538 
539 //! Sets the precision parameter used for irrational calculations.
540 /*! The lesser between numerator and denominator is limited to 2**\p p.
541 
542   If \p p is less than or equal to <CODE>INT_MAX</CODE>, sets the
543   precision parameter used for irrational calculations to \p p.
544 
545   \exception std::invalid_argument
546   Thrown if \p p is greater than <CODE>INT_MAX</CODE>.
547 */
548 inline void
set_irrational_precision(const unsigned p)549 set_irrational_precision(const unsigned p) {
550   if (p <= INT_MAX) {
551     Checked::irrational_precision = p;
552   }
553   else {
554     throw std::invalid_argument("PPL::set_irrational_precision(p)"
555                                 " with p > INT_MAX");
556   }
557 }
558 
559 } // namespace Parma_Polyhedra_Library
560 
561 #endif // !defined(PPL_checked_mpq_inlines_hh)
562