1 /* Specialized "checked" functions for GMP's mpz_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_mpz_inlines_hh
25 #define PPL_checked_mpz_inlines_hh 1
26
27 #include <sstream>
28
29 namespace Parma_Polyhedra_Library {
30
31 namespace Checked {
32
33 template <typename Policy>
34 inline Result
round_lt_mpz(mpz_class & to,Rounding_Dir dir)35 round_lt_mpz(mpz_class& to, Rounding_Dir dir) {
36 if (round_down(dir)) {
37 --to;
38 return V_GT;
39 }
40 return V_LT;
41 }
42
43 template <typename Policy>
44 inline Result
round_gt_mpz(mpz_class & to,Rounding_Dir dir)45 round_gt_mpz(mpz_class& to, Rounding_Dir dir) {
46 if (round_up(dir)) {
47 ++to;
48 return V_LT;
49 }
50 return V_GT;
51 }
52
53 #if __cplusplus >= 201103L
54 //! Type of the _mp_size field of GMP's __mpz_struct.
55 typedef decltype(__mpz_struct()._mp_size) mp_size_field_t;
56 #elif PPL_HAVE_TYPEOF
57 //! Type of the _mp_size field of GMP's __mpz_struct.
58 typedef typeof(__mpz_struct()._mp_size) mp_size_field_t;
59 #else
60 //! This is assumed to be the type of the _mp_size field of GMP's __mpz_struct.
61 typedef int mp_size_field_t;
62 #endif
63
64 inline mp_size_field_t
get_mp_size(const mpz_class & v)65 get_mp_size(const mpz_class &v) {
66 return v.get_mpz_t()->_mp_size;
67 }
68
69 inline void
set_mp_size(mpz_class & v,mp_size_field_t size)70 set_mp_size(mpz_class &v, mp_size_field_t size) {
71 v.get_mpz_t()->_mp_size = size;
72 }
73
74 template <typename Policy>
75 inline Result
classify_mpz(const mpz_class & v,bool nan,bool inf,bool sign)76 classify_mpz(const mpz_class& v, bool nan, bool inf, bool sign) {
77 if (Policy::has_nan || Policy::has_infinity) {
78 mp_size_field_t s = get_mp_size(v);
79 if (Policy::has_nan
80 && (nan || sign)
81 && s == C_Integer<mp_size_field_t>::min + 1) {
82 return V_NAN;
83 }
84 if (!inf && !sign) {
85 return V_LGE;
86 }
87 if (Policy::has_infinity) {
88 if (s == C_Integer<mp_size_field_t>::min) {
89 return inf ? V_EQ_MINUS_INFINITY : V_LT;
90 }
91 if (s == C_Integer<mp_size_field_t>::max) {
92 return inf ? V_EQ_PLUS_INFINITY : V_GT;
93 }
94 }
95 }
96 if (sign) {
97 return static_cast<Result>(sgn<Policy>(v));
98 }
99 return V_LGE;
100 }
101
PPL_SPECIALIZE_CLASSIFY(classify_mpz,mpz_class)102 PPL_SPECIALIZE_CLASSIFY(classify_mpz, mpz_class)
103
104 template <typename Policy>
105 inline bool
106 is_nan_mpz(const mpz_class& v) {
107 return Policy::has_nan
108 && get_mp_size(v) == C_Integer<mp_size_field_t>::min + 1;
109 }
110
PPL_SPECIALIZE_IS_NAN(is_nan_mpz,mpz_class)111 PPL_SPECIALIZE_IS_NAN(is_nan_mpz, mpz_class)
112
113 template <typename Policy>
114 inline bool
115 is_minf_mpz(const mpz_class& v) {
116 return Policy::has_infinity
117 && get_mp_size(v) == C_Integer<mp_size_field_t>::min;
118 }
119
PPL_SPECIALIZE_IS_MINF(is_minf_mpz,mpz_class)120 PPL_SPECIALIZE_IS_MINF(is_minf_mpz, mpz_class)
121
122 template <typename Policy>
123 inline bool
124 is_pinf_mpz(const mpz_class& v) {
125 return Policy::has_infinity
126 && get_mp_size(v) == C_Integer<mp_size_field_t>::max;
127 }
128
PPL_SPECIALIZE_IS_PINF(is_pinf_mpz,mpz_class)129 PPL_SPECIALIZE_IS_PINF(is_pinf_mpz, mpz_class)
130
131 template <typename Policy>
132 inline bool
133 is_int_mpz(const mpz_class& v) {
134 return !is_nan<Policy>(v);
135 }
136
PPL_SPECIALIZE_IS_INT(is_int_mpz,mpz_class)137 PPL_SPECIALIZE_IS_INT(is_int_mpz, mpz_class)
138
139 template <typename Policy>
140 inline Result
141 assign_special_mpz(mpz_class& v, Result_Class c, Rounding_Dir) {
142 switch (c) {
143 case VC_NAN:
144 if (Policy::has_nan) {
145 set_mp_size(v, C_Integer<mp_size_field_t>::min + 1);
146 }
147 return V_NAN;
148 case VC_MINUS_INFINITY:
149 if (Policy::has_infinity) {
150 set_mp_size(v, C_Integer<mp_size_field_t>::min);
151 return V_EQ_MINUS_INFINITY;
152 }
153 return V_EQ_MINUS_INFINITY | V_UNREPRESENTABLE;
154 case VC_PLUS_INFINITY:
155 if (Policy::has_infinity) {
156 set_mp_size(v, C_Integer<mp_size_field_t>::max);
157 return V_EQ_PLUS_INFINITY;
158 }
159 return V_EQ_PLUS_INFINITY | V_UNREPRESENTABLE;
160 default:
161 PPL_UNREACHABLE;
162 return V_NAN;
163 }
164 }
165
PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_mpz,mpz_class)166 PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_mpz, mpz_class)
167
168 template <typename To_Policy, typename From_Policy>
169 inline void
170 copy_mpz(mpz_class& to, const mpz_class& from) {
171 if (is_nan_mpz<From_Policy>(from)) {
172 PPL_ASSERT(To_Policy::has_nan);
173 }
174 else if (is_minf_mpz<From_Policy>(from) || is_pinf_mpz<From_Policy>(from)) {
175 PPL_ASSERT(To_Policy::has_infinity);
176 }
177 else {
178 to = from;
179 return;
180 }
181 set_mp_size(to, get_mp_size(from));
182 }
183
PPL_SPECIALIZE_COPY(copy_mpz,mpz_class)184 PPL_SPECIALIZE_COPY(copy_mpz, mpz_class)
185
186 template <typename To_Policy, typename From_Policy, typename From>
187 inline Result
188 construct_mpz_base(mpz_class& to, const From from, Rounding_Dir) {
189 new(&to) mpz_class(from);
190 return V_EQ;
191 }
192
PPL_SPECIALIZE_CONSTRUCT(construct_mpz_base,mpz_class,char)193 PPL_SPECIALIZE_CONSTRUCT(construct_mpz_base, mpz_class, char)
194 PPL_SPECIALIZE_CONSTRUCT(construct_mpz_base, mpz_class, signed char)
195 PPL_SPECIALIZE_CONSTRUCT(construct_mpz_base, mpz_class, signed short)
196 PPL_SPECIALIZE_CONSTRUCT(construct_mpz_base, mpz_class, signed int)
197 PPL_SPECIALIZE_CONSTRUCT(construct_mpz_base, mpz_class, signed long)
198 PPL_SPECIALIZE_CONSTRUCT(construct_mpz_base, mpz_class, unsigned char)
199 PPL_SPECIALIZE_CONSTRUCT(construct_mpz_base, mpz_class, unsigned short)
200 PPL_SPECIALIZE_CONSTRUCT(construct_mpz_base, mpz_class, unsigned int)
201 PPL_SPECIALIZE_CONSTRUCT(construct_mpz_base, mpz_class, unsigned long)
202
203 template <typename To_Policy, typename From_Policy, typename From>
204 inline Result
205 construct_mpz_float(mpz_class& to, const From& from, Rounding_Dir dir) {
206 if (is_nan<From_Policy>(from)) {
207 return construct_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
208 }
209 else if (is_minf<From_Policy>(from)) {
210 return construct_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
211 }
212 else if (is_pinf<From_Policy>(from)) {
213 return construct_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
214 }
215 if (round_not_requested(dir)) {
216 new(&to) mpz_class(from);
217 return V_LGE;
218 }
219 From n = rint(from);
220 new(&to) mpz_class(n);
221 if (from == n) {
222 return V_EQ;
223 }
224 if (from < 0) {
225 return round_lt_mpz<To_Policy>(to, dir);
226 }
227 else {
228 return round_gt_mpz<To_Policy>(to, dir);
229 }
230 }
231
PPL_SPECIALIZE_CONSTRUCT(construct_mpz_float,mpz_class,float)232 PPL_SPECIALIZE_CONSTRUCT(construct_mpz_float, mpz_class, float)
233 PPL_SPECIALIZE_CONSTRUCT(construct_mpz_float, mpz_class, double)
234
235 PPL_SPECIALIZE_ASSIGN(assign_exact, mpz_class, mpz_class)
236 PPL_SPECIALIZE_ASSIGN(assign_exact, mpz_class, char)
237 PPL_SPECIALIZE_ASSIGN(assign_exact, mpz_class, signed char)
238 PPL_SPECIALIZE_ASSIGN(assign_exact, mpz_class, signed short)
239 PPL_SPECIALIZE_ASSIGN(assign_exact, mpz_class, signed int)
240 PPL_SPECIALIZE_ASSIGN(assign_exact, mpz_class, signed long)
241 PPL_SPECIALIZE_ASSIGN(assign_exact, mpz_class, unsigned char)
242 PPL_SPECIALIZE_ASSIGN(assign_exact, mpz_class, unsigned short)
243 PPL_SPECIALIZE_ASSIGN(assign_exact, mpz_class, unsigned int)
244 PPL_SPECIALIZE_ASSIGN(assign_exact, mpz_class, unsigned long)
245
246 template <typename To_Policy, typename From_Policy, typename From>
247 inline Result
248 assign_mpz_signed_int(mpz_class& to, const From from, Rounding_Dir) {
249 if (sizeof(From) <= sizeof(signed long)) {
250 to = static_cast<signed long>(from);
251 }
252 else {
253 mpz_ptr m = to.get_mpz_t();
254 if (from >= 0) {
255 mpz_import(m, 1, 1, sizeof(From), 0, 0, &from);
256 }
257 else {
258 From n = -from;
259 mpz_import(m, 1, 1, sizeof(From), 0, 0, &n);
260 mpz_neg(m, m);
261 }
262 }
263 return V_EQ;
264 }
265
PPL_SPECIALIZE_ASSIGN(assign_mpz_signed_int,mpz_class,signed long long)266 PPL_SPECIALIZE_ASSIGN(assign_mpz_signed_int, mpz_class, signed long long)
267
268 template <typename To_Policy, typename From_Policy, typename From>
269 inline Result
270 assign_mpz_unsigned_int(mpz_class& to, const From from, Rounding_Dir) {
271 if (sizeof(From) <= sizeof(unsigned long)) {
272 to = static_cast<unsigned long>(from);
273 }
274 else {
275 mpz_import(to.get_mpz_t(), 1, 1, sizeof(From), 0, 0, &from);
276 }
277 return V_EQ;
278 }
279
PPL_SPECIALIZE_ASSIGN(assign_mpz_unsigned_int,mpz_class,unsigned long long)280 PPL_SPECIALIZE_ASSIGN(assign_mpz_unsigned_int, mpz_class, unsigned long long)
281
282 template <typename To_Policy, typename From_Policy, typename From>
283 inline Result
284 assign_mpz_float(mpz_class& to, const From from, Rounding_Dir dir) {
285 if (is_nan<From_Policy>(from)) {
286 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
287 }
288 else if (is_minf<From_Policy>(from)) {
289 return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
290 }
291 else if (is_pinf<From_Policy>(from)) {
292 return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
293 }
294 if (round_not_requested(dir)) {
295 to = from;
296 return V_LGE;
297 }
298 From i_from = rint(from);
299 to = i_from;
300 if (from == i_from) {
301 return V_EQ;
302 }
303 if (round_direct(ROUND_UP)) {
304 return round_lt_mpz<To_Policy>(to, dir);
305 }
306 if (round_direct(ROUND_DOWN)) {
307 return round_gt_mpz<To_Policy>(to, dir);
308 }
309 if (from < i_from) {
310 return round_lt_mpz<To_Policy>(to, dir);
311 }
312 if (from > i_from) {
313 return round_gt_mpz<To_Policy>(to, dir);
314 }
315 PPL_UNREACHABLE;
316 return V_NAN;
317 }
318
PPL_SPECIALIZE_ASSIGN(assign_mpz_float,mpz_class,float)319 PPL_SPECIALIZE_ASSIGN(assign_mpz_float, mpz_class, float)
320 PPL_SPECIALIZE_ASSIGN(assign_mpz_float, mpz_class, double)
321
322 template <typename To_Policy, typename From_Policy, typename From>
323 inline Result
324 assign_mpz_long_double(mpz_class& to, const From& from, Rounding_Dir dir) {
325 if (is_nan<From_Policy>(from)) {
326 return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
327 }
328 else if (is_minf<From_Policy>(from)) {
329 return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
330 }
331 else if (is_pinf<From_Policy>(from)) {
332 return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
333 }
334 // FIXME: this is an incredibly inefficient implementation!
335 std::stringstream ss;
336 output<From_Policy>(ss, from, Numeric_Format(), dir);
337 PPL_DIRTY_TEMP(mpq_class, tmp);
338 #ifndef NDEBUG
339 Result r =
340 #endif
341 input_mpq(tmp, ss);
342 PPL_ASSERT(r == V_EQ);
343 return assign<To_Policy, From_Policy>(to, tmp, dir);
344 }
345
PPL_SPECIALIZE_ASSIGN(assign_mpz_long_double,mpz_class,long double)346 PPL_SPECIALIZE_ASSIGN(assign_mpz_long_double, mpz_class, long double)
347
348 template <typename To_Policy, typename From_Policy>
349 inline Result
350 assign_mpz_mpq(mpz_class& to, const mpq_class& from, Rounding_Dir dir) {
351 if (round_not_needed(dir)) {
352 to = from.get_num();
353 return V_LGE;
354 }
355 if (round_ignore(dir)) {
356 to = from;
357 return V_LGE;
358 }
359 const mpz_srcptr n = from.get_num().get_mpz_t();
360 const mpz_srcptr d = from.get_den().get_mpz_t();
361 if (round_down(dir)) {
362 mpz_fdiv_q(to.get_mpz_t(), n, d);
363 if (round_strict_relation(dir)) {
364 return (mpz_divisible_p(n, d) != 0) ? V_EQ : V_GT;
365 }
366 return V_GE;
367 }
368 else {
369 PPL_ASSERT(round_up(dir));
370 mpz_cdiv_q(to.get_mpz_t(), n, d);
371 if (round_strict_relation(dir)) {
372 return (mpz_divisible_p(n, d) != 0) ? V_EQ : V_LT;
373 }
374 return V_LE;
375 }
376 }
377
PPL_SPECIALIZE_ASSIGN(assign_mpz_mpq,mpz_class,mpq_class)378 PPL_SPECIALIZE_ASSIGN(assign_mpz_mpq, mpz_class, mpq_class)
379
380 PPL_SPECIALIZE_FLOOR(assign_exact, mpz_class, mpz_class)
381 PPL_SPECIALIZE_CEIL(assign_exact, mpz_class, mpz_class)
382 PPL_SPECIALIZE_TRUNC(assign_exact, mpz_class, mpz_class)
383
384 template <typename To_Policy, typename From_Policy>
385 inline Result
386 neg_mpz(mpz_class& to, const mpz_class& from, Rounding_Dir) {
387 mpz_neg(to.get_mpz_t(), from.get_mpz_t());
388 return V_EQ;
389 }
390
PPL_SPECIALIZE_NEG(neg_mpz,mpz_class,mpz_class)391 PPL_SPECIALIZE_NEG(neg_mpz, mpz_class, mpz_class)
392
393 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
394 inline Result
395 add_mpz(mpz_class& to, const mpz_class& x, const mpz_class& y, Rounding_Dir) {
396 to = x + y;
397 return V_EQ;
398 }
399
PPL_SPECIALIZE_ADD(add_mpz,mpz_class,mpz_class,mpz_class)400 PPL_SPECIALIZE_ADD(add_mpz, mpz_class, mpz_class, mpz_class)
401
402 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
403 inline Result
404 sub_mpz(mpz_class& to, const mpz_class& x, const mpz_class& y, Rounding_Dir) {
405 to = x - y;
406 return V_EQ;
407 }
408
PPL_SPECIALIZE_SUB(sub_mpz,mpz_class,mpz_class,mpz_class)409 PPL_SPECIALIZE_SUB(sub_mpz, mpz_class, mpz_class, mpz_class)
410
411 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
412 inline Result
413 mul_mpz(mpz_class& to, const mpz_class& x, const mpz_class& y, Rounding_Dir) {
414 to = x * y;
415 return V_EQ;
416 }
417
PPL_SPECIALIZE_MUL(mul_mpz,mpz_class,mpz_class,mpz_class)418 PPL_SPECIALIZE_MUL(mul_mpz, mpz_class, mpz_class, mpz_class)
419
420 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
421 inline Result
422 div_mpz(mpz_class& to, const mpz_class& x, const mpz_class& y,
423 Rounding_Dir dir) {
424 if (CHECK_P(To_Policy::check_div_zero, ::sgn(y) == 0)) {
425 return assign_nan<To_Policy>(to, V_DIV_ZERO);
426 }
427 const mpz_srcptr n = x.get_mpz_t();
428 const mpz_srcptr d = y.get_mpz_t();
429 if (round_not_needed(dir)) {
430 mpz_divexact(to.get_mpz_t(), n, d);
431 return V_LGE;
432 }
433 if (round_ignore(dir)) {
434 mpz_cdiv_q(to.get_mpz_t(), n, d);
435 return V_LE;
436 }
437 if (round_down(dir)) {
438 mpz_fdiv_q(to.get_mpz_t(), n, d);
439 if (round_strict_relation(dir)) {
440 return (mpz_divisible_p(n, d) != 0) ? V_EQ : V_GT;
441 }
442 return V_GE;
443 }
444 else {
445 PPL_ASSERT(round_up(dir));
446 mpz_cdiv_q(to.get_mpz_t(), n, d);
447 if (round_strict_relation(dir)) {
448 return (mpz_divisible_p(n, d) != 0) ? V_EQ : V_LT;
449 }
450 return V_LE;
451 }
452 }
453
PPL_SPECIALIZE_DIV(div_mpz,mpz_class,mpz_class,mpz_class)454 PPL_SPECIALIZE_DIV(div_mpz, mpz_class, mpz_class, mpz_class)
455
456 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
457 inline Result
458 idiv_mpz(mpz_class& to, const mpz_class& x, const mpz_class& y,
459 Rounding_Dir) {
460 if (CHECK_P(To_Policy::check_div_zero, ::sgn(y) == 0)) {
461 return assign_nan<To_Policy>(to, V_DIV_ZERO);
462 }
463 mpz_srcptr n = x.get_mpz_t();
464 mpz_srcptr d = y.get_mpz_t();
465 mpz_tdiv_q(to.get_mpz_t(), n, d);
466 return V_EQ;
467 }
468
PPL_SPECIALIZE_IDIV(idiv_mpz,mpz_class,mpz_class,mpz_class)469 PPL_SPECIALIZE_IDIV(idiv_mpz, mpz_class, mpz_class, mpz_class)
470
471 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
472 inline Result
473 rem_mpz(mpz_class& to, const mpz_class& x, const mpz_class& y, Rounding_Dir) {
474 if (CHECK_P(To_Policy::check_div_zero, ::sgn(y) == 0)) {
475 return assign_nan<To_Policy>(to, V_MOD_ZERO);
476 }
477 to = x % y;
478 return V_EQ;
479 }
480
PPL_SPECIALIZE_REM(rem_mpz,mpz_class,mpz_class,mpz_class)481 PPL_SPECIALIZE_REM(rem_mpz, mpz_class, mpz_class, mpz_class)
482
483 template <typename To_Policy, typename From_Policy>
484 inline Result
485 add_2exp_mpz(mpz_class& to, const mpz_class& x, unsigned int exp,
486 Rounding_Dir) {
487 PPL_DIRTY_TEMP(mpz_class, v);
488 v = 1;
489 mpz_mul_2exp(v.get_mpz_t(), v.get_mpz_t(), exp);
490 to = x + v;
491 return V_EQ;
492 }
493
PPL_SPECIALIZE_ADD_2EXP(add_2exp_mpz,mpz_class,mpz_class)494 PPL_SPECIALIZE_ADD_2EXP(add_2exp_mpz, mpz_class, mpz_class)
495
496 template <typename To_Policy, typename From_Policy>
497 inline Result
498 sub_2exp_mpz(mpz_class& to, const mpz_class& x, unsigned int exp,
499 Rounding_Dir) {
500 PPL_DIRTY_TEMP(mpz_class, v);
501 v = 1;
502 mpz_mul_2exp(v.get_mpz_t(), v.get_mpz_t(), exp);
503 to = x - v;
504 return V_EQ;
505 }
506
PPL_SPECIALIZE_SUB_2EXP(sub_2exp_mpz,mpz_class,mpz_class)507 PPL_SPECIALIZE_SUB_2EXP(sub_2exp_mpz, mpz_class, mpz_class)
508
509 template <typename To_Policy, typename From_Policy>
510 inline Result
511 mul_2exp_mpz(mpz_class& to, const mpz_class& x, unsigned int exp,
512 Rounding_Dir) {
513 mpz_mul_2exp(to.get_mpz_t(), x.get_mpz_t(), exp);
514 return V_EQ;
515 }
516
PPL_SPECIALIZE_MUL_2EXP(mul_2exp_mpz,mpz_class,mpz_class)517 PPL_SPECIALIZE_MUL_2EXP(mul_2exp_mpz, mpz_class, mpz_class)
518
519 template <typename To_Policy, typename From_Policy>
520 inline Result
521 div_2exp_mpz(mpz_class& to, const mpz_class& x, unsigned int exp,
522 Rounding_Dir dir) {
523 const mpz_srcptr n = x.get_mpz_t();
524 if (round_not_requested(dir)) {
525 mpz_tdiv_q_2exp(to.get_mpz_t(), x.get_mpz_t(), exp);
526 return V_LGE;
527 }
528 if (round_down(dir)) {
529 mpz_fdiv_q_2exp(to.get_mpz_t(), n, exp);
530 if (round_strict_relation(dir)) {
531 return (mpz_divisible_2exp_p(n, exp) != 0) ? V_EQ : V_GT;
532 }
533 return V_GE;
534 }
535 else {
536 PPL_ASSERT(round_up(dir));
537 mpz_cdiv_q_2exp(to.get_mpz_t(), n, exp);
538 if (round_strict_relation(dir)) {
539 return (mpz_divisible_2exp_p(n, exp) != 0) ? V_EQ : V_LT;
540 }
541 return V_LE;
542 }
543 }
544
PPL_SPECIALIZE_DIV_2EXP(div_2exp_mpz,mpz_class,mpz_class)545 PPL_SPECIALIZE_DIV_2EXP(div_2exp_mpz, mpz_class, mpz_class)
546
547 template <typename To_Policy, typename From_Policy>
548 inline Result
549 smod_2exp_mpz(mpz_class& to, const mpz_class& x, unsigned int exp,
550 Rounding_Dir) {
551 if (mpz_tstbit(x.get_mpz_t(), exp - 1) != 0) {
552 mpz_cdiv_r_2exp(to.get_mpz_t(), x.get_mpz_t(), exp);
553 }
554 else {
555 mpz_fdiv_r_2exp(to.get_mpz_t(), x.get_mpz_t(), exp);
556 }
557 return V_EQ;
558 }
559
PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_mpz,mpz_class,mpz_class)560 PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_mpz, mpz_class, mpz_class)
561
562 template <typename To_Policy, typename From_Policy>
563 inline Result
564 umod_2exp_mpz(mpz_class& to, const mpz_class& x, unsigned int exp,
565 Rounding_Dir) {
566 mpz_fdiv_r_2exp(to.get_mpz_t(), x.get_mpz_t(), exp);
567 return V_EQ;
568 }
569
PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_mpz,mpz_class,mpz_class)570 PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_mpz, mpz_class, mpz_class)
571
572 template <typename To_Policy, typename From_Policy>
573 inline Result
574 abs_mpz(mpz_class& to, const mpz_class& from, Rounding_Dir) {
575 to = abs(from);
576 return V_EQ;
577 }
578
PPL_SPECIALIZE_ABS(abs_mpz,mpz_class,mpz_class)579 PPL_SPECIALIZE_ABS(abs_mpz, mpz_class, mpz_class)
580
581 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
582 inline Result
583 add_mul_mpz(mpz_class& to, const mpz_class& x, const mpz_class& y,
584 Rounding_Dir) {
585 mpz_addmul(to.get_mpz_t(), x.get_mpz_t(), y.get_mpz_t());
586 return V_EQ;
587 }
588
PPL_SPECIALIZE_ADD_MUL(add_mul_mpz,mpz_class,mpz_class,mpz_class)589 PPL_SPECIALIZE_ADD_MUL(add_mul_mpz, mpz_class, mpz_class, mpz_class)
590
591 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
592 inline Result
593 sub_mul_mpz(mpz_class& to, const mpz_class& x, const mpz_class& y,
594 Rounding_Dir) {
595 mpz_submul(to.get_mpz_t(), x.get_mpz_t(), y.get_mpz_t());
596 return V_EQ;
597 }
598
PPL_SPECIALIZE_SUB_MUL(sub_mul_mpz,mpz_class,mpz_class,mpz_class)599 PPL_SPECIALIZE_SUB_MUL(sub_mul_mpz, mpz_class, mpz_class, mpz_class)
600
601 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
602 inline Result
603 gcd_mpz(mpz_class& to, const mpz_class& x, const mpz_class& y, Rounding_Dir) {
604 mpz_gcd(to.get_mpz_t(), x.get_mpz_t(), y.get_mpz_t());
605 return V_EQ;
606 }
607
PPL_SPECIALIZE_GCD(gcd_mpz,mpz_class,mpz_class,mpz_class)608 PPL_SPECIALIZE_GCD(gcd_mpz, mpz_class, mpz_class, mpz_class)
609
610 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
611 inline Result
612 gcdext_mpz(mpz_class& to, mpz_class& s, mpz_class& t,
613 const mpz_class& x, const mpz_class& y,
614 Rounding_Dir) {
615 mpz_gcdext(to.get_mpz_t(), s.get_mpz_t(), t.get_mpz_t(),
616 x.get_mpz_t(), y.get_mpz_t());
617 return V_EQ;
618 }
619
PPL_SPECIALIZE_GCDEXT(gcdext_mpz,mpz_class,mpz_class,mpz_class,mpz_class,mpz_class)620 PPL_SPECIALIZE_GCDEXT(gcdext_mpz, mpz_class, mpz_class, mpz_class, mpz_class, mpz_class)
621
622 template <typename To_Policy, typename From1_Policy, typename From2_Policy>
623 inline Result
624 lcm_mpz(mpz_class& to, const mpz_class& x, const mpz_class& y, Rounding_Dir) {
625 mpz_lcm(to.get_mpz_t(), x.get_mpz_t(), y.get_mpz_t());
626 return V_EQ;
627 }
628
PPL_SPECIALIZE_LCM(lcm_mpz,mpz_class,mpz_class,mpz_class)629 PPL_SPECIALIZE_LCM(lcm_mpz, mpz_class, mpz_class, mpz_class)
630
631 template <typename To_Policy, typename From_Policy>
632 inline Result
633 sqrt_mpz(mpz_class& to, const mpz_class& from, Rounding_Dir dir) {
634 if (CHECK_P(To_Policy::check_sqrt_neg, from < 0)) {
635 return assign_nan<To_Policy>(to, V_SQRT_NEG);
636 }
637 if (round_not_requested(dir)) {
638 to = sqrt(from);
639 return V_GE;
640 }
641 PPL_DIRTY_TEMP(mpz_class, r);
642 mpz_sqrtrem(to.get_mpz_t(), r.get_mpz_t(), from.get_mpz_t());
643 if (r == 0) {
644 return V_EQ;
645 }
646 return round_gt_mpz<To_Policy>(to, dir);
647 }
648
PPL_SPECIALIZE_SQRT(sqrt_mpz,mpz_class,mpz_class)649 PPL_SPECIALIZE_SQRT(sqrt_mpz, mpz_class, mpz_class)
650
651 template <typename Policy, typename Type>
652 inline Result_Relation
653 sgn_mp(const Type& x) {
654 const int sign = ::sgn(x);
655 return (sign > 0) ? VR_GT : ((sign < 0) ? VR_LT : VR_EQ);
656 }
657
PPL_SPECIALIZE_SGN(sgn_mp,mpz_class)658 PPL_SPECIALIZE_SGN(sgn_mp, mpz_class)
659 PPL_SPECIALIZE_SGN(sgn_mp, mpq_class)
660
661 template <typename Policy1, typename Policy2, typename Type>
662 inline Result_Relation
663 cmp_mp(const Type& x, const Type& y) {
664 int i = ::cmp(x, y);
665 return (i > 0) ? VR_GT : ((i < 0) ? VR_LT : VR_EQ);
666 }
667
PPL_SPECIALIZE_CMP(cmp_mp,mpz_class,mpz_class)668 PPL_SPECIALIZE_CMP(cmp_mp, mpz_class, mpz_class)
669 PPL_SPECIALIZE_CMP(cmp_mp, mpq_class, mpq_class)
670
671 template <typename Policy>
672 inline Result
673 output_mpz(std::ostream& os, const mpz_class& from, const Numeric_Format&,
674 Rounding_Dir) {
675 os << from;
676 return V_EQ;
677 }
678
679 PPL_SPECIALIZE_INPUT(input_generic, mpz_class)
680 PPL_SPECIALIZE_OUTPUT(output_mpz, mpz_class)
681
682 } // namespace Checked
683
684 } // namespace Parma_Polyhedra_Library
685
686 #endif // !defined(PPL_checked_mpz_inlines_hh)
687