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