1 /* Checked_Number class implementation: inline functions.
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_Number_inlines_hh
25 #define PPL_Checked_Number_inlines_hh 1
26 
27 #include "globals_defs.hh"
28 #include <stdexcept>
29 #include <sstream>
30 
31 namespace Parma_Polyhedra_Library {
32 
33 #ifndef NDEBUG
34 #define DEBUG_ROUND_NOT_NEEDED
35 #endif
36 
37 inline Rounding_Dir
rounding_dir(Rounding_Dir dir)38 rounding_dir(Rounding_Dir dir) {
39   if (dir == ROUND_NOT_NEEDED) {
40 #ifdef DEBUG_ROUND_NOT_NEEDED
41     return ROUND_CHECK;
42 #endif
43   }
44   return dir;
45 }
46 
47 inline Result
check_result(Result r,Rounding_Dir dir)48 check_result(Result r, Rounding_Dir dir) {
49   if (dir == ROUND_NOT_NEEDED) {
50 #ifdef DEBUG_ROUND_NOT_NEEDED
51     PPL_ASSERT(result_relation(r) == VR_EQ);
52 #endif
53     return r;
54   }
55   return r;
56 }
57 
58 
59 template <typename T>
60 inline void
handle_result(Result)61 Checked_Number_Transparent_Policy<T>::handle_result(Result) {
62 }
63 
64 inline void
handle_result(Result r)65 Extended_Number_Policy::handle_result(Result r) {
66   if (result_class(r) == VC_NAN) {
67     throw_result_exception(r);
68   }
69 }
70 
71 template <typename T, typename Policy>
72 inline
Checked_Number()73 Checked_Number<T, Policy>::Checked_Number()
74  : v(0) {
75 }
76 
77 template <typename T, typename Policy>
78 inline
Checked_Number(const Checked_Number & y)79 Checked_Number<T, Policy>::Checked_Number(const Checked_Number& y) {
80   // TODO: avoid default construction of value member.
81   Checked::copy<Policy, Policy>(v, y.raw_value());
82 }
83 
84 template <typename T, typename Policy>
85 template <typename From, typename From_Policy>
86 inline
87 Checked_Number<T, Policy>
Checked_Number(const Checked_Number<From,From_Policy> & y,Rounding_Dir dir)88 ::Checked_Number(const Checked_Number<From, From_Policy>& y,
89                  Rounding_Dir dir) {
90   // TODO: avoid default construction of value member.
91   Policy::handle_result(check_result(Checked::assign_ext<Policy, From_Policy>
92                                      (v,
93                                       y.raw_value(),
94                                       rounding_dir(dir)),
95                                      dir)
96                         );
97 }
98 
99 template <typename T, typename Policy>
100 template <typename From, typename From_Policy>
101 inline
102 Checked_Number<T, Policy>
Checked_Number(const Checked_Number<From,From_Policy> & y)103 ::Checked_Number(const Checked_Number<From, From_Policy>& y) {
104   // TODO: avoid default construction of value member.
105   Rounding_Dir dir = Policy::ROUND_DEFAULT_CONSTRUCTOR;
106   Policy::handle_result(check_result(Checked::assign_ext<Policy, From_Policy>
107                                      (v,
108                                       y.raw_value(),
109                                       rounding_dir(dir)),
110                                      dir));
111 }
112 
113 // TODO: avoid default construction of value member.
114 #define PPL_DEFINE_CTOR(type) \
115 template <typename T, typename Policy> \
116 inline \
117 Checked_Number<T, Policy>::Checked_Number(const type y, Rounding_Dir dir) { \
118   Policy::handle_result(check_result(Checked::assign_ext<Policy,        \
119                                      Checked_Number_Transparent_Policy<PPL_U(type)> > \
120                                      (v, y, rounding_dir(dir)),         \
121                                      dir));                             \
122 }                                                                       \
123 template <typename T, typename Policy>                                  \
124 inline                                                                  \
125 Checked_Number<T, Policy>::Checked_Number(const type y) {               \
126   Rounding_Dir dir = Policy::ROUND_DEFAULT_CONSTRUCTOR;                 \
127   Policy::handle_result(check_result(Checked::assign_ext<Policy,        \
128                                      Checked_Number_Transparent_Policy<PPL_U(type)> > \
129                                      (v, y, rounding_dir(dir)),         \
130                                      dir));                             \
131 }
132 
133 PPL_DEFINE_CTOR(char)
PPL_DEFINE_CTOR(signed char)134 PPL_DEFINE_CTOR(signed char)
135 PPL_DEFINE_CTOR(signed short)
136 PPL_DEFINE_CTOR(signed int)
137 PPL_DEFINE_CTOR(signed long)
138 PPL_DEFINE_CTOR(signed long long)
139 PPL_DEFINE_CTOR(unsigned char)
140 PPL_DEFINE_CTOR(unsigned short)
141 PPL_DEFINE_CTOR(unsigned int)
142 PPL_DEFINE_CTOR(unsigned long)
143 PPL_DEFINE_CTOR(unsigned long long)
144 #if PPL_SUPPORTED_FLOAT
145 PPL_DEFINE_CTOR(float)
146 #endif
147 #if PPL_SUPPORTED_DOUBLE
148 PPL_DEFINE_CTOR(double)
149 #endif
150 #if PPL_SUPPORTED_LONG_DOUBLE
151 PPL_DEFINE_CTOR(long double)
152 #endif
153 PPL_DEFINE_CTOR(mpq_class&)
154 PPL_DEFINE_CTOR(mpz_class&)
155 
156 #undef PPL_DEFINE_CTOR
157 
158 
159 template <typename T, typename Policy>
160 inline
161 Checked_Number<T, Policy>::Checked_Number(const char* y, Rounding_Dir dir) {
162   std::istringstream s(y);
163   Policy::handle_result(check_result(Checked::input<Policy>(v,
164                                                             s,
165                                                             rounding_dir(dir)),
166                                      dir));
167 }
168 
169 template <typename T, typename Policy>
170 inline
Checked_Number(const char * y)171 Checked_Number<T, Policy>::Checked_Number(const char* y) {
172   std::istringstream s(y);
173   Rounding_Dir dir = Policy::ROUND_DEFAULT_CONSTRUCTOR;
174   Policy::handle_result(check_result(Checked::input<Policy>(v,
175                                                             s,
176                                                             rounding_dir(dir)),
177                                      dir));
178 }
179 
180 template <typename T, typename Policy>
181 template <typename From>
182 inline
183 Checked_Number<T, Policy>
Checked_Number(const From &,Rounding_Dir dir,typename Enable_If<Is_Special<From>::value,bool>::type)184 ::Checked_Number(const From&,
185                  Rounding_Dir dir,
186                  typename Enable_If<Is_Special<From>::value, bool>::type) {
187   Policy::handle_result(check_result(Checked::assign_special<Policy>(v,
188                                                                      From::vclass,
189                                                                      rounding_dir(dir)),
190                                      dir));
191 }
192 
193 template <typename T, typename Policy>
194 template <typename From>
195 inline
Checked_Number(const From &,typename Enable_If<Is_Special<From>::value,bool>::type)196 Checked_Number<T, Policy>::Checked_Number(const From&, typename Enable_If<Is_Special<From>::value, bool>::type) {
197   Rounding_Dir dir = Policy::ROUND_DEFAULT_CONSTRUCTOR;
198   Policy::handle_result(check_result(Checked::assign_special<Policy>(v,
199                                                             From::vclass,
200                                                             rounding_dir(dir)),
201                                      dir));
202 }
203 
204 template <typename To, typename From>
205 inline typename Enable_If<Is_Native_Or_Checked<To>::value
206                           && Is_Special<From>::value, Result>::type
assign_r(To & to,const From &,Rounding_Dir dir)207 assign_r(To& to, const From&, Rounding_Dir dir) {
208   return check_result(Checked::assign_special<typename Native_Checked_To_Wrapper<To>
209                       ::Policy>(Native_Checked_To_Wrapper<To>::raw_value(to),
210                                 From::vclass,
211                                 rounding_dir(dir)),
212                       dir);
213 }
214 
215 template <typename To, typename From>
216 inline typename Enable_If<Is_Native_Or_Checked<To>::value && Is_Special<From>::value, Result>::type
construct(To & to,const From &,Rounding_Dir dir)217 construct(To& to, const From&, Rounding_Dir dir) {
218   return check_result(Checked::construct_special<typename Native_Checked_To_Wrapper<To>
219                       ::Policy>(Native_Checked_To_Wrapper<To>::raw_value(to),
220                                 From::vclass,
221                                 rounding_dir(dir)),
222                       dir);
223 }
224 
225 template <typename T>
226 inline typename Enable_If<Is_Native_Or_Checked<T>::value, bool>::type
is_minus_infinity(const T & x)227 is_minus_infinity(const T& x) {
228   return Checked::is_minf<typename Native_Checked_From_Wrapper<T>
229     ::Policy>(Native_Checked_From_Wrapper<T>::raw_value(x));
230 }
231 
232 template <typename T>
233 inline typename Enable_If<Is_Native_Or_Checked<T>::value, bool>::type
is_plus_infinity(const T & x)234 is_plus_infinity(const T& x) {
235   return Checked::is_pinf<typename Native_Checked_From_Wrapper<T>
236     ::Policy>(Native_Checked_From_Wrapper<T>::raw_value(x));
237 }
238 
239 template <typename T>
240 inline typename Enable_If<Is_Native_Or_Checked<T>::value, int>::type
infinity_sign(const T & x)241 infinity_sign(const T& x) {
242   return is_minus_infinity(x) ? -1 : (is_plus_infinity(x) ? 1 : 0);
243 }
244 
245 template <typename T>
246 inline typename Enable_If<Is_Native_Or_Checked<T>::value, bool>::type
is_not_a_number(const T & x)247 is_not_a_number(const T& x) {
248   return Checked::is_nan<typename Native_Checked_From_Wrapper<T>
249     ::Policy>(Native_Checked_From_Wrapper<T>::raw_value(x));
250 }
251 
252 template <typename T>
253 inline typename Enable_If<Is_Native_Or_Checked<T>::value, bool>::type
is_integer(const T & x)254 is_integer(const T& x) {
255   return Checked::is_int<typename Native_Checked_From_Wrapper<T>
256     ::Policy>(Native_Checked_From_Wrapper<T>::raw_value(x));
257 }
258 
259 template <typename T, typename Policy>
260 inline
operator T() const261 Checked_Number<T, Policy>::operator T() const {
262   if (Policy::convertible) {
263     return v;
264   }
265 }
266 
267 template <typename T, typename Policy>
268 inline T&
raw_value()269 Checked_Number<T, Policy>::raw_value() {
270   return v;
271 }
272 
273 template <typename T, typename Policy>
274 inline const T&
raw_value() const275 Checked_Number<T, Policy>::raw_value() const {
276   return v;
277 }
278 
279 /*! \relates Checked_Number */
280 template <typename T, typename Policy>
281 inline const T&
raw_value(const Checked_Number<T,Policy> & x)282 raw_value(const Checked_Number<T, Policy>& x) {
283   return x.raw_value();
284 }
285 
286 /*! \relates Checked_Number */
287 template <typename T, typename Policy>
288 inline T&
raw_value(Checked_Number<T,Policy> & x)289 raw_value(Checked_Number<T, Policy>& x) {
290   return x.raw_value();
291 }
292 
293 template <typename T, typename Policy>
294 inline bool
OK() const295 Checked_Number<T, Policy>::OK() const {
296   return true;
297 }
298 
299 template <typename T, typename Policy>
300 inline Result
classify(bool nan,bool inf,bool sign) const301 Checked_Number<T, Policy>::classify(bool nan, bool inf, bool sign) const {
302   return Checked::classify<Policy>(v, nan, inf, sign);
303 }
304 
305 template <typename T, typename Policy>
306 inline bool
is_not_a_number(const Checked_Number<T,Policy> & x)307 is_not_a_number(const Checked_Number<T, Policy>& x) {
308   return Checked::is_nan<Policy>(x.raw_value());
309 }
310 
311 template <typename T, typename Policy>
312 inline bool
is_minus_infinity(const Checked_Number<T,Policy> & x)313 is_minus_infinity(const Checked_Number<T, Policy>& x) {
314   return Checked::is_minf<Policy>(x.raw_value());
315 }
316 
317 template <typename T, typename Policy>
318 inline bool
is_plus_infinity(const Checked_Number<T,Policy> & x)319 is_plus_infinity(const Checked_Number<T, Policy>& x) {
320   return Checked::is_pinf<Policy>(x.raw_value());
321 }
322 
323 /*! \relates Checked_Number */
324 template <typename T, typename Policy>
325 inline memory_size_type
total_memory_in_bytes(const Checked_Number<T,Policy> & x)326 total_memory_in_bytes(const Checked_Number<T, Policy>& x) {
327   return total_memory_in_bytes(x.raw_value());
328 }
329 
330 /*! \relates Checked_Number */
331 template <typename T, typename Policy>
332 inline memory_size_type
external_memory_in_bytes(const Checked_Number<T,Policy> & x)333 external_memory_in_bytes(const Checked_Number<T, Policy>& x) {
334   return external_memory_in_bytes(x.raw_value());
335 }
336 
337 
338 /*! \relates Checked_Number */
339 template <typename To>
340 inline typename Enable_If<Is_Native_Or_Checked<To>::value, Result>::type
assign_r(To & to,const char * x,Rounding_Dir dir)341 assign_r(To& to, const char* x, Rounding_Dir dir) {
342   std::istringstream s(x);
343   return check_result(Checked::input<typename Native_Checked_To_Wrapper<To>
344                       ::Policy>(Native_Checked_To_Wrapper<To>::raw_value(to),
345                                 s,
346                                 rounding_dir(dir)),
347                       dir);
348 }
349 
350 #define PPL_DEFINE_FUNC1_A(name, func) \
351 template <typename To, typename From>                                   \
352 inline typename Enable_If<Is_Native_Or_Checked<To>::value               \
353                           && Is_Native_Or_Checked<From>::value,         \
354                           Result>::type                                 \
355  PPL_U(name)(To& to, const From& x, Rounding_Dir dir) {                 \
356   return                                                                \
357     check_result(Checked::func<typename Native_Checked_To_Wrapper<To>   \
358                  ::Policy,                                              \
359                  typename Native_Checked_From_Wrapper<From>             \
360                  ::Policy>(Native_Checked_To_Wrapper<To>::raw_value(to), \
361                            Native_Checked_From_Wrapper<From>::raw_value(x), \
362                            rounding_dir(dir)), dir);                    \
363 }
364 
PPL_DEFINE_FUNC1_A(construct,construct_ext)365 PPL_DEFINE_FUNC1_A(construct, construct_ext)
366 PPL_DEFINE_FUNC1_A(assign_r, assign_ext)
367 PPL_DEFINE_FUNC1_A(floor_assign_r, floor_ext)
368 PPL_DEFINE_FUNC1_A(ceil_assign_r, ceil_ext)
369 PPL_DEFINE_FUNC1_A(trunc_assign_r, trunc_ext)
370 PPL_DEFINE_FUNC1_A(neg_assign_r, neg_ext)
371 PPL_DEFINE_FUNC1_A(abs_assign_r, abs_ext)
372 PPL_DEFINE_FUNC1_A(sqrt_assign_r, sqrt_ext)
373 
374 #undef PPL_DEFINE_FUNC1_A
375 
376 #define PPL_DEFINE_FUNC1_B(name, func) \
377 template <typename To, typename From>                                   \
378 inline typename Enable_If<Is_Native_Or_Checked<To>::value               \
379                           && Is_Native_Or_Checked<From>::value,         \
380                           Result>::type                                 \
381  PPL_U(name)(To& to, const From& x, unsigned int exp, Rounding_Dir dir) { \
382   return                                                                \
383     check_result(Checked::func<typename Native_Checked_To_Wrapper<To>   \
384                  ::Policy,                                              \
385                  typename Native_Checked_From_Wrapper<From>             \
386                  ::Policy>(Native_Checked_To_Wrapper<To>::raw_value(to), \
387                            Native_Checked_From_Wrapper<From>::raw_value(x), \
388                            exp,                                         \
389                            rounding_dir(dir)),                          \
390                  dir);                                                  \
391 }
392 
393 PPL_DEFINE_FUNC1_B(add_2exp_assign_r, add_2exp_ext)
394 PPL_DEFINE_FUNC1_B(sub_2exp_assign_r, sub_2exp_ext)
395 PPL_DEFINE_FUNC1_B(mul_2exp_assign_r, mul_2exp_ext)
396 PPL_DEFINE_FUNC1_B(div_2exp_assign_r, div_2exp_ext)
397 PPL_DEFINE_FUNC1_B(smod_2exp_assign_r, smod_2exp_ext)
398 PPL_DEFINE_FUNC1_B(umod_2exp_assign_r, umod_2exp_ext)
399 
400 #undef PPL_DEFINE_FUNC1_B
401 
402 #define PPL_DEFINE_FUNC2(name, func) \
403 template <typename To, typename From1, typename From2>                  \
404 inline typename Enable_If<Is_Native_Or_Checked<To>::value               \
405                           && Is_Native_Or_Checked<From1>::value         \
406                           && Is_Native_Or_Checked<From2>::value,        \
407                           Result>::type                                 \
408  PPL_U(name)(To& to, const From1& x, const From2& y, Rounding_Dir dir) { \
409   return                                                                \
410     check_result(Checked::func<typename Native_Checked_To_Wrapper<To>   \
411                  ::Policy,                                              \
412                  typename Native_Checked_From_Wrapper<From1>            \
413                  ::Policy,                                              \
414                  typename Native_Checked_From_Wrapper<From2>            \
415                  ::Policy>(Native_Checked_To_Wrapper<To>::raw_value(to), \
416                            Native_Checked_From_Wrapper<From1>::raw_value(x), \
417                            Native_Checked_From_Wrapper<From2>::raw_value(y), \
418                            rounding_dir(dir)),                          \
419                  dir);                                                  \
420 }
421 
422 PPL_DEFINE_FUNC2(add_assign_r, add_ext)
423 PPL_DEFINE_FUNC2(sub_assign_r, sub_ext)
424 PPL_DEFINE_FUNC2(mul_assign_r, mul_ext)
425 PPL_DEFINE_FUNC2(div_assign_r, div_ext)
426 PPL_DEFINE_FUNC2(idiv_assign_r, idiv_ext)
427 PPL_DEFINE_FUNC2(rem_assign_r, rem_ext)
428 PPL_DEFINE_FUNC2(gcd_assign_r, gcd_ext)
429 PPL_DEFINE_FUNC2(lcm_assign_r, lcm_ext)
430 PPL_DEFINE_FUNC2(add_mul_assign_r, add_mul_ext)
431 PPL_DEFINE_FUNC2(sub_mul_assign_r, sub_mul_ext)
432 
433 #undef PPL_DEFINE_FUNC2
434 
435 #define PPL_DEFINE_FUNC4(name, func)                                    \
436 template <typename To1,                                                 \
437           typename To2,                                                 \
438           typename To3,                                                 \
439           typename From1,                                               \
440           typename From2>                                               \
441 inline typename Enable_If<Is_Native_Or_Checked<To1>::value              \
442                           && Is_Native_Or_Checked<To2>::value           \
443                           && Is_Native_Or_Checked<To3>::value           \
444                           && Is_Native_Or_Checked<From1>::value         \
445                           && Is_Native_Or_Checked<From2>::value,        \
446                           Result>::type                                 \
447  PPL_U(name)(To1& to, To2& s, To3& t, const From1& x, const From2& y,   \
448      Rounding_Dir dir) {                                                \
449   return                                                                \
450     check_result(Checked::func<typename Native_Checked_To_Wrapper<To1>::Policy, \
451                  typename Native_Checked_To_Wrapper<To2>::Policy,       \
452                  typename Native_Checked_To_Wrapper<To3>::Policy,       \
453                  typename Native_Checked_From_Wrapper<From1>::Policy,   \
454                  typename Native_Checked_From_Wrapper<From2>::Policy>   \
455                  (Native_Checked_To_Wrapper<To1>::raw_value(to),        \
456                   Native_Checked_To_Wrapper<To2>::raw_value(s),         \
457                   Native_Checked_To_Wrapper<To3>::raw_value(t),         \
458                   Native_Checked_From_Wrapper<From1>::raw_value(x),     \
459                   Native_Checked_From_Wrapper<From2>::raw_value(y),     \
460                   rounding_dir(dir)),                                   \
461                  dir);                                                  \
462 }
463 
464 PPL_DEFINE_FUNC4(gcdext_assign_r, gcdext_ext)
465 
466 #undef PPL_DEFINE_PPL_DEFINE_FUNC4
467 
468 #define PPL_DEFINE_INCREMENT(f, fun) \
469 template <typename T, typename Policy> \
470 inline Checked_Number<T, Policy>& \
471 Checked_Number<T, Policy>::f() { \
472   Policy::handle_result((fun)(*this, *this, T(1),             \
473                             Policy::ROUND_DEFAULT_OPERATOR)); \
474   return *this; \
475 } \
476 template <typename T, typename Policy> \
477 inline Checked_Number<T, Policy> \
478 Checked_Number<T, Policy>::f(int) {\
479   T r = v;\
480   Policy::handle_result((fun)(*this, *this, T(1),             \
481                             Policy::ROUND_DEFAULT_OPERATOR)); \
482   return r;\
483 }
484 
485 PPL_DEFINE_INCREMENT(operator ++, add_assign_r)
486 PPL_DEFINE_INCREMENT(operator --, sub_assign_r)
487 
488 #undef PPL_DEFINE_INCREMENT
489 
490 template <typename T, typename Policy>
491 inline Checked_Number<T, Policy>&
492 Checked_Number<T, Policy>::operator=(const Checked_Number<T, Policy>& y) {
493   Checked::copy<Policy, Policy>(v, y.raw_value());
494   return *this;
495 }
496 template <typename T, typename Policy>
497 template <typename From>
498 inline Checked_Number<T, Policy>&
operator =(const From & y)499 Checked_Number<T, Policy>::operator=(const From& y) {
500   Policy::handle_result(assign_r(*this, y, Policy::ROUND_DEFAULT_OPERATOR));
501   return *this;
502 }
503 
504 #define PPL_DEFINE_BINARY_OP_ASSIGN(f, fun) \
505 template <typename T, typename Policy> \
506 template <typename From_Policy> \
507 inline Checked_Number<T, Policy>& \
508 Checked_Number<T, Policy>::f(const Checked_Number<T, From_Policy>& y) { \
509   Policy::handle_result((fun)(*this, *this, y,                          \
510                             Policy::ROUND_DEFAULT_OPERATOR)); \
511   return *this; \
512 } \
513 template <typename T, typename Policy> \
514 inline Checked_Number<T, Policy>& \
515 Checked_Number<T, Policy>::f(const T& y) { \
516   Policy::handle_result((fun)(*this, *this, y,                \
517                             Policy::ROUND_DEFAULT_OPERATOR)); \
518   return *this; \
519 } \
520 template <typename T, typename Policy> \
521 template <typename From> \
522 inline typename Enable_If<Is_Native_Or_Checked<From>::value, \
523                           Checked_Number<T, Policy>& >::type \
524 Checked_Number<T, Policy>::f(const From& y) { \
525   Checked_Number<T, Policy> cy(y); \
526   Policy::handle_result((fun)(*this, *this, cy,               \
527                             Policy::ROUND_DEFAULT_OPERATOR)); \
528   return *this; \
529 }
530 
531 PPL_DEFINE_BINARY_OP_ASSIGN(operator +=, add_assign_r)
532 PPL_DEFINE_BINARY_OP_ASSIGN(operator -=, sub_assign_r)
533 PPL_DEFINE_BINARY_OP_ASSIGN(operator *=, mul_assign_r)
534 PPL_DEFINE_BINARY_OP_ASSIGN(operator /=, div_assign_r)
535 PPL_DEFINE_BINARY_OP_ASSIGN(operator %=, rem_assign_r)
536 
537 #undef PPL_DEFINE_BINARY_OP_ASSIGN
538 
539 #define PPL_DEFINE_BINARY_OP(f, fun) \
540 template <typename T, typename Policy> \
541 inline Checked_Number<T, Policy> \
542  PPL_U(f)(const Checked_Number<T, Policy>& x,   \
543          const Checked_Number<T, Policy>& y) {  \
544   Checked_Number<T, Policy> r; \
545   Policy::handle_result((fun)(r, x, y, Policy::ROUND_DEFAULT_OPERATOR)); \
546   return r; \
547 } \
548 template <typename Type, typename T, typename Policy>   \
549 inline \
550 typename Enable_If<Is_Native<Type>::value, Checked_Number<T, Policy> >::type \
551  PPL_U(f)(const Type& x, const Checked_Number<T, Policy>& y) {          \
552   Checked_Number<T, Policy> r(x); \
553   Policy::handle_result((fun)(r, r, y, Policy::ROUND_DEFAULT_OPERATOR)); \
554   return r; \
555 } \
556 template <typename T, typename Policy, typename Type>   \
557 inline \
558 typename Enable_If<Is_Native<Type>::value, Checked_Number<T, Policy> >::type \
559  PPL_U(f)(const Checked_Number<T, Policy>& x, const Type& y) {          \
560   Checked_Number<T, Policy> r(y); \
561   Policy::handle_result((fun)(r, x, r, Policy::ROUND_DEFAULT_OPERATOR)); \
562   return r; \
563 }
564 
565 PPL_DEFINE_BINARY_OP(operator +, add_assign_r)
566 PPL_DEFINE_BINARY_OP(operator -, sub_assign_r)
567 PPL_DEFINE_BINARY_OP(operator *, mul_assign_r)
568 PPL_DEFINE_BINARY_OP(operator /, div_assign_r)
569 PPL_DEFINE_BINARY_OP(operator %, rem_assign_r)
570 
571 #undef PPL_DEFINE_BINARY_OP
572 
573 #define PPL_DEFINE_COMPARE_OP(f, fun)                                   \
574 template <typename T1, typename T2>                                     \
575 inline                                                                  \
576 typename Enable_If<Is_Native_Or_Checked<T1>::value                      \
577                    && Is_Native_Or_Checked<T2>::value                   \
578                    && (Is_Checked<T1>::value || Is_Checked<T2>::value), \
579                    bool>::type                                          \
580  PPL_U(f)(const T1& x, const T2& y) {                                   \
581   return Checked::fun<typename Native_Checked_From_Wrapper<T1>::Policy, \
582                       typename Native_Checked_From_Wrapper<T2>::Policy> \
583     (Native_Checked_From_Wrapper<T1>::raw_value(x),                     \
584      Native_Checked_From_Wrapper<T2>::raw_value(y));                    \
585 }
586 
587 PPL_DEFINE_COMPARE_OP(operator ==, eq_ext)
588 PPL_DEFINE_COMPARE_OP(operator !=, ne_ext)
589 PPL_DEFINE_COMPARE_OP(operator >=, ge_ext)
590 PPL_DEFINE_COMPARE_OP(operator >, gt_ext)
591 PPL_DEFINE_COMPARE_OP(operator <=, le_ext)
592 PPL_DEFINE_COMPARE_OP(operator <, lt_ext)
593 
594 #undef PPL_DEFINE_COMPARE_OP
595 
596 #define PPL_DEFINE_COMPARE(f, fun)                                      \
597 template <typename T1, typename T2>                                     \
598 inline typename Enable_If<Is_Native_Or_Checked<T1>::value               \
599                           && Is_Native_Or_Checked<T2>::value,           \
600                           bool>::type                                   \
601  PPL_U(f)(const T1& x, const T2& y) {                                   \
602   return Checked::fun<typename Native_Checked_From_Wrapper<T1>::Policy, \
603                       typename Native_Checked_From_Wrapper<T2>::Policy> \
604     (Native_Checked_From_Wrapper<T1>::raw_value(x),                     \
605      Native_Checked_From_Wrapper<T2>::raw_value(y));                    \
606 }
607 
608 PPL_DEFINE_COMPARE(equal, eq_ext)
609 PPL_DEFINE_COMPARE(not_equal, ne_ext)
610 PPL_DEFINE_COMPARE(greater_or_equal, ge_ext)
611 PPL_DEFINE_COMPARE(greater_than, gt_ext)
612 PPL_DEFINE_COMPARE(less_or_equal, le_ext)
613 PPL_DEFINE_COMPARE(less_than, lt_ext)
614 
615 #undef PPL_DEFINE_COMPARE
616 
617 /*! \relates Checked_Number */
618 template <typename T, typename Policy>
619 inline Checked_Number<T, Policy>
620 operator+(const Checked_Number<T, Policy>& x) {
621   return x;
622 }
623 
624 /*! \relates Checked_Number */
625 template <typename T, typename Policy>
626 inline Checked_Number<T, Policy>
operator -(const Checked_Number<T,Policy> & x)627 operator-(const Checked_Number<T, Policy>& x) {
628   Checked_Number<T, Policy> r;
629   Policy::handle_result(neg_assign_r(r, x, Policy::ROUND_DEFAULT_OPERATOR));
630   return r;
631 }
632 
633 #define PPL_DEFINE_ASSIGN_FUN2_1(f, fun) \
634 template <typename T, typename Policy> \
635 inline void \
636  PPL_U(f)(Checked_Number<T, Policy>& x) {                               \
637   Policy::handle_result((fun)(x, x, Policy::ROUND_DEFAULT_FUNCTION));   \
638 }
639 
640 #define PPL_DEFINE_ASSIGN_FUN2_2(f, fun) \
641 template <typename T, typename Policy> \
642 inline void \
643  PPL_U(f)(Checked_Number<T, Policy>& x, const Checked_Number<T, Policy>& y) { \
644   Policy::handle_result((fun)(x, y, Policy::ROUND_DEFAULT_FUNCTION)); \
645 }
646 
647 #define PPL_DEFINE_ASSIGN_FUN3_3(f, fun) \
648 template <typename T, typename Policy> \
649 inline void \
650  PPL_U(f)(Checked_Number<T, Policy>& x, const Checked_Number<T, Policy>& y, \
651   const Checked_Number<T, Policy>& z) { \
652   Policy::handle_result((fun)(x, y, z, Policy::ROUND_DEFAULT_FUNCTION)); \
653 }
654 
655 #define PPL_DEFINE_ASSIGN_FUN5_5(f, fun)                                        \
656 template <typename T, typename Policy>                                  \
657 inline void                                                             \
658  PPL_U(f)(Checked_Number<T, Policy>& x,                                 \
659   Checked_Number<T, Policy>& s, Checked_Number<T, Policy>& t,           \
660   const Checked_Number<T, Policy>& y,                                   \
661   const Checked_Number<T, Policy>& z) {                                 \
662   Policy::handle_result((fun)(x, s, t, y, z, Policy::ROUND_DEFAULT_FUNCTION)); \
663 }
664 
PPL_DEFINE_ASSIGN_FUN2_2(sqrt_assign,sqrt_assign_r)665 PPL_DEFINE_ASSIGN_FUN2_2(sqrt_assign, sqrt_assign_r)
666 
667 PPL_DEFINE_ASSIGN_FUN2_1(floor_assign, floor_assign_r)
668 PPL_DEFINE_ASSIGN_FUN2_2(floor_assign, floor_assign_r)
669 
670 PPL_DEFINE_ASSIGN_FUN2_1(ceil_assign, ceil_assign_r)
671 PPL_DEFINE_ASSIGN_FUN2_2(ceil_assign, ceil_assign_r)
672 
673 PPL_DEFINE_ASSIGN_FUN2_1(trunc_assign, trunc_assign_r)
674 PPL_DEFINE_ASSIGN_FUN2_2(trunc_assign, trunc_assign_r)
675 
676 PPL_DEFINE_ASSIGN_FUN2_1(neg_assign, neg_assign_r)
677 PPL_DEFINE_ASSIGN_FUN2_2(neg_assign, neg_assign_r)
678 
679 PPL_DEFINE_ASSIGN_FUN2_1(abs_assign, abs_assign_r)
680 PPL_DEFINE_ASSIGN_FUN2_2(abs_assign, abs_assign_r)
681 
682 PPL_DEFINE_ASSIGN_FUN3_3(add_mul_assign, add_mul_assign_r)
683 
684 PPL_DEFINE_ASSIGN_FUN3_3(sub_mul_assign, sub_mul_assign_r)
685 
686 PPL_DEFINE_ASSIGN_FUN3_3(rem_assign, rem_assign_r)
687 
688 PPL_DEFINE_ASSIGN_FUN3_3(gcd_assign, gcd_assign_r)
689 
690 PPL_DEFINE_ASSIGN_FUN5_5(gcdext_assign, gcdext_assign_r)
691 
692 PPL_DEFINE_ASSIGN_FUN3_3(lcm_assign, lcm_assign_r)
693 
694 #undef PPL_DEFINE_ASSIGN_FUN2_1
695 #undef PPL_DEFINE_ASSIGN_FUN2_2
696 #undef PPL_DEFINE_ASSIGN_FUN3_2
697 #undef PPL_DEFINE_ASSIGN_FUN3_3
698 #undef PPL_DEFINE_ASSIGN_FUN5_5
699 
700 #define PPL_DEFINE_ASSIGN_2EXP(f, fun)                                  \
701 template <typename T, typename Policy>                                  \
702 inline void                                                             \
703  PPL_U(f)(Checked_Number<T, Policy>& x,                                 \
704           const Checked_Number<T, Policy>& y, unsigned int exp) {       \
705   Policy::handle_result((fun)(x, y, exp, Policy::ROUND_DEFAULT_FUNCTION)); \
706 }
707 
708 PPL_DEFINE_ASSIGN_2EXP(mul_2exp_assign, mul_2exp_assign_r)
709 PPL_DEFINE_ASSIGN_2EXP(div_2exp_assign, div_2exp_assign_r)
710 
711 template <typename T, typename Policy>
712 inline void
713 exact_div_assign(Checked_Number<T, Policy>& x,
714                  const Checked_Number<T, Policy>& y,
715                  const Checked_Number<T, Policy>& z) {
716   Policy::handle_result(div_assign_r(x, y, z, ROUND_NOT_NEEDED));
717 }
718 
719 /*! \relates Checked_Number */
720 template <typename From>
721 inline typename Enable_If<Is_Native_Or_Checked<From>::value, int>::type
sgn(const From & x)722 sgn(const From& x) {
723   Result_Relation r
724     = Checked::sgn_ext<typename Native_Checked_From_Wrapper<From>::Policy>
725         (Native_Checked_From_Wrapper<From>::raw_value(x));
726   switch (r) {
727   case VR_LT:
728     return -1;
729   case VR_EQ:
730     return 0;
731   case VR_GT:
732     return 1;
733   default:
734     throw(0);
735   }
736 }
737 
738 /*! \relates Checked_Number */
739 template <typename From1, typename From2>
740 inline typename Enable_If<Is_Native_Or_Checked<From1>::value
741                           && Is_Native_Or_Checked<From2>::value,
742                           int>::type
cmp(const From1 & x,const From2 & y)743 cmp(const From1& x, const From2& y) {
744   Result_Relation r
745     = Checked::cmp_ext<typename Native_Checked_From_Wrapper<From1>::Policy,
746                        typename Native_Checked_From_Wrapper<From2>::Policy>
747                  (Native_Checked_From_Wrapper<From1>::raw_value(x),
748                   Native_Checked_From_Wrapper<From2>::raw_value(y));
749   switch (r) {
750   case VR_LT:
751     return -1;
752   case VR_EQ:
753     return 0;
754   case VR_GT:
755     return 1;
756   default:
757     throw(0);
758   }
759 }
760 
761 /*! \relates Checked_Number */
762 template <typename T>
763 typename Enable_If<Is_Native_Or_Checked<T>::value, Result>::type
output(std::ostream & os,const T & x,const Numeric_Format & format,Rounding_Dir dir)764 output(std::ostream& os, const T& x,
765        const Numeric_Format& format, Rounding_Dir dir) {
766   return check_result(Checked::output_ext<typename Native_Checked_From_Wrapper<T>::Policy>
767                       (os,
768                        Native_Checked_From_Wrapper<T>::raw_value(x),
769                        format,
770                        rounding_dir(dir)),
771                       dir);
772 }
773 
774 /*! \relates Checked_Number */
775 template <typename T, typename Policy>
776 inline std::ostream&
operator <<(std::ostream & os,const Checked_Number<T,Policy> & x)777 operator<<(std::ostream& os, const Checked_Number<T, Policy>& x) {
778   Policy::handle_result(output(os, x, Numeric_Format(), ROUND_IGNORE));
779   return os;
780 }
781 
782 /*! \relates Checked_Number */
783 template <typename T>
784 typename Enable_If<Is_Native_Or_Checked<T>::value, Result>::type
input(T & x,std::istream & is,Rounding_Dir dir)785 input(T& x, std::istream& is, Rounding_Dir dir) {
786   return check_result(Checked::input_ext<typename Native_Checked_To_Wrapper<T>::Policy>
787                       (Native_Checked_To_Wrapper<T>::raw_value(x),
788                        is,
789                        rounding_dir(dir)),
790                       dir);
791 }
792 
793 /*! \relates Checked_Number */
794 template <typename T, typename Policy>
operator >>(std::istream & is,Checked_Number<T,Policy> & x)795 inline std::istream& operator>>(std::istream& is,
796                                 Checked_Number<T, Policy>& x) {
797   Result r = input(x, is, Policy::ROUND_DEFAULT_INPUT);
798   if (r == V_CVT_STR_UNK) {
799     is.setstate(std::ios::failbit);
800   }
801   else {
802     Policy::handle_result(r);
803   }
804   return is;
805 }
806 
807 template <typename T>
808 inline T
plus_infinity()809 plus_infinity() {
810   return PLUS_INFINITY;
811 }
812 
813 template <typename T>
814 inline T
minus_infinity()815 minus_infinity() {
816   return MINUS_INFINITY;
817 }
818 
819 template <typename T>
820 inline T
not_a_number()821 not_a_number() {
822   return NOT_A_NUMBER;
823 }
824 
825 /*! \relates Checked_Number */
826 template <typename T, typename Policy>
827 inline void
swap(Checked_Number<T,Policy> & x,Checked_Number<T,Policy> & y)828 swap(Checked_Number<T, Policy>& x, Checked_Number<T, Policy>& y) {
829   using std::swap;
830   swap(x.raw_value(), y.raw_value());
831 }
832 
833 template <typename T>
834 inline void
maybe_reset_fpu_inexact()835 maybe_reset_fpu_inexact() {
836   if (FPU_Related<T>::value) {
837     return fpu_reset_inexact();
838   }
839 }
840 
841 template <typename T>
842 inline int
maybe_check_fpu_inexact()843 maybe_check_fpu_inexact() {
844   if (FPU_Related<T>::value) {
845     return fpu_check_inexact();
846   }
847   else {
848     return 0;
849   }
850 }
851 
852 } // namespace Parma_Polyhedra_Library
853 
854 #endif // !defined(PPL_Checked_Number_inlines_hh)
855