PPL  1.2
checked_ext_inlines.hh
Go to the documentation of this file.
1 /* Checked extended arithmetic 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_ext_defs_hh
25 #define PPL_checked_ext_defs_hh 1
26 
27 namespace Parma_Polyhedra_Library {
28 
29 template <typename T> struct FPU_Related : public False {};
30 template <> struct FPU_Related<float> : public True {};
31 template <> struct FPU_Related<double> : public True {};
32 template <> struct FPU_Related<long double> : public True {};
33 
34 namespace Checked {
35 
36 template <typename T>
37 inline bool
39  return FPU_Related<T>::value;
40 }
41 
42 template <typename Policy, typename Type>
43 inline bool
44 ext_to_handle(const Type& x) {
45  return !handle_ext_natively(x)
46  && (Policy::has_infinity || Policy::has_nan);
47 }
48 
49 template <typename Policy, typename Type>
50 inline Result_Relation
51 sgn_ext(const Type& x) {
52  if (!ext_to_handle<Policy>(x)) {
53  goto native;
54  }
55  if (is_nan<Policy>(x)) {
56  return VR_EMPTY;
57  }
58  else if (is_minf<Policy>(x)) {
59  return VR_LT;
60  }
61  else if (is_pinf<Policy>(x)) {
62  return VR_GT;
63  }
64  else {
65  native:
66  return sgn<Policy>(x);
67  }
68 }
69 
70 template <typename To_Policy, typename From_Policy,
71  typename To, typename From>
72 inline Result
73 construct_ext(To& to, const From& x, Rounding_Dir dir) {
74  if (!ext_to_handle<From_Policy>(x)) {
75  goto native;
76  }
77  if (is_nan<From_Policy>(x)) {
78  return construct_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
79  }
80  else if (is_minf<From_Policy>(x)) {
81  return construct_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
82  }
83  else if (is_pinf<From_Policy>(x)) {
84  return construct_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
85  }
86  else {
87  native:
88  return construct<To_Policy, From_Policy>(to, x, dir);
89  }
90 }
91 
92 template <typename To_Policy, typename From_Policy,
93  typename To, typename From>
94 inline Result
95 assign_ext(To& to, const From& x, Rounding_Dir dir) {
96  if (!ext_to_handle<From_Policy>(x)) {
97  goto native;
98  }
99  if (is_nan<From_Policy>(x)) {
100  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
101  }
102  else if (is_minf<From_Policy>(x)) {
103  return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
104  }
105  else if (is_pinf<From_Policy>(x)) {
106  return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
107  }
108  else {
109  native:
110  return assign<To_Policy, From_Policy>(to, x, dir);
111  }
112 }
113 
114 template <typename To_Policy, typename From_Policy,
115  typename To, typename From>
116 inline Result
117 neg_ext(To& to, const From& x, Rounding_Dir dir) {
118  if (!ext_to_handle<From_Policy>(x)) {
119  goto native;
120  }
121  if (is_nan<From_Policy>(x)) {
122  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
123  }
124  else if (is_minf<From_Policy>(x)) {
125  return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
126  }
127  else if (is_pinf<From_Policy>(x)) {
128  return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
129  }
130  else {
131  native:
132  return neg<To_Policy, From_Policy>(to, x, dir);
133  }
134 }
135 
136 template <typename To_Policy, typename From_Policy,
137  typename To, typename From>
138 inline Result
139 floor_ext(To& to, const From& x, Rounding_Dir dir) {
140  if (!ext_to_handle<From_Policy>(x)) {
141  goto native;
142  }
143  if (is_nan<From_Policy>(x)) {
144  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
145  }
146  else if (is_minf<From_Policy>(x)) {
147  return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
148  }
149  else if (is_pinf<From_Policy>(x)) {
150  return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
151  }
152  else {
153  native:
154  return floor<To_Policy, From_Policy>(to, x, dir);
155  }
156 }
157 
158 template <typename To_Policy, typename From_Policy,
159  typename To, typename From>
160 inline Result
161 ceil_ext(To& to, const From& x, Rounding_Dir dir) {
162  if (!ext_to_handle<From_Policy>(x)) {
163  goto native;
164  }
165  if (is_nan<From_Policy>(x)) {
166  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
167  }
168  else if (is_minf<From_Policy>(x)) {
169  return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
170  }
171  else if (is_pinf<From_Policy>(x)) {
172  return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
173  }
174  else {
175  native:
176  return ceil<To_Policy, From_Policy>(to, x, dir);
177  }
178 }
179 
180 template <typename To_Policy, typename From_Policy,
181  typename To, typename From>
182 inline Result
183 trunc_ext(To& to, const From& x, Rounding_Dir dir) {
184  if (!ext_to_handle<From_Policy>(x)) {
185  goto native;
186  }
187  if (is_nan<From_Policy>(x)) {
188  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
189  }
190  else if (is_minf<From_Policy>(x)) {
191  return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
192  }
193  else if (is_pinf<From_Policy>(x)) {
194  return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
195  }
196  else {
197  native:
198  return trunc<To_Policy, From_Policy>(to, x, dir);
199  }
200 }
201 
202 template <typename To_Policy, typename From_Policy,
203  typename To, typename From>
204 inline Result
205 abs_ext(To& to, const From& x, Rounding_Dir dir) {
206  if (!ext_to_handle<From_Policy>(x)) {
207  goto native;
208  }
209  if (is_nan<From_Policy>(x)) {
210  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
211  }
212  else if (is_minf<From_Policy>(x) || is_pinf<From_Policy>(x)) {
213  return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
214  }
215  else {
216  native:
217  return abs<To_Policy, From_Policy>(to, x, dir);
218  }
219 }
220 
221 template <typename To_Policy, typename From1_Policy, typename From2_Policy,
222  typename To, typename From1, typename From2>
223 inline Result
224 add_ext(To& to, const From1& x, const From2& y, Rounding_Dir dir) {
225  if (!ext_to_handle<From1_Policy>(x) && !ext_to_handle<From2_Policy>(y)) {
226  goto native;
227  }
228  if (is_nan<From1_Policy>(x) || is_nan<From2_Policy>(y)) {
229  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
230  }
231  else if (is_minf<From1_Policy>(x)) {
232  if (CHECK_P(To_Policy::check_inf_add_inf, is_pinf<From2_Policy>(y))) {
233  goto inf_add_inf;
234  }
235  else {
236  goto minf;
237  }
238  }
239  else if (is_pinf<From1_Policy>(x)) {
240  if (CHECK_P(To_Policy::check_inf_add_inf, is_minf<From2_Policy>(y))) {
241  inf_add_inf:
242  return assign_nan<To_Policy>(to, V_INF_ADD_INF);
243  }
244  else {
245  goto pinf;
246  }
247  }
248  else {
249  if (is_minf<From2_Policy>(y)) {
250  minf:
251  return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
252  }
253  else if (is_pinf<From2_Policy>(y)) {
254  pinf:
255  return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
256  }
257  else {
258  native:
259  return add<To_Policy, From1_Policy, From2_Policy>(to, x, y, dir);
260  }
261  }
262 }
263 
264 template <typename To_Policy, typename From1_Policy, typename From2_Policy,
265  typename To, typename From1, typename From2>
266 inline Result
267 sub_ext(To& to, const From1& x, const From2& y, Rounding_Dir dir) {
268  if (!ext_to_handle<From1_Policy>(x) && !ext_to_handle<From2_Policy>(y)) {
269  goto native;
270  }
271  if (is_nan<From1_Policy>(x) || is_nan<From2_Policy>(y)) {
272  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
273  }
274  else if (is_minf<From1_Policy>(x)) {
275  if (CHECK_P(To_Policy::check_inf_sub_inf, is_minf<From2_Policy>(y))) {
276  goto inf_sub_inf;
277  }
278  else {
279  goto minf;
280  }
281  }
282  else if (is_pinf<From1_Policy>(x)) {
283  if (CHECK_P(To_Policy::check_inf_sub_inf, is_pinf<From2_Policy>(y))) {
284  inf_sub_inf:
285  return assign_nan<To_Policy>(to, V_INF_SUB_INF);
286  }
287  else {
288  goto pinf;
289  }
290  }
291  else {
292  if (is_pinf<From2_Policy>(y)) {
293  minf:
294  return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
295  }
296  else if (is_minf<From2_Policy>(y)) {
297  pinf:
298  return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
299  }
300  else {
301  native:
302  return sub<To_Policy, From1_Policy, From2_Policy>(to, x, y, dir);
303  }
304  }
305 }
306 
307 template <typename To_Policy, typename From1_Policy, typename From2_Policy,
308  typename To, typename From1, typename From2>
309 inline Result
310 mul_ext(To& to, const From1& x, const From2& y, Rounding_Dir dir) {
311  if (!ext_to_handle<From1_Policy>(x) && !ext_to_handle<From2_Policy>(y)) {
312  goto native;
313  }
314  if (is_nan<From1_Policy>(x) || is_nan<From2_Policy>(y)) {
315  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
316  }
317  if (is_minf<From1_Policy>(x)) {
318  switch (sgn_ext<From2_Policy>(y)) {
319  case VR_LT:
320  goto pinf;
321  case VR_GT:
322  goto minf;
323  default:
324  goto inf_mul_zero;
325  }
326  }
327  else if (is_pinf<From1_Policy>(x)) {
328  switch (sgn_ext<From2_Policy>(y)) {
329  case VR_LT:
330  goto minf;
331  case VR_GT:
332  goto pinf;
333  default:
334  goto inf_mul_zero;
335  }
336  }
337  else {
338  if (is_minf<From2_Policy>(y)) {
339  switch (sgn<From1_Policy>(x)) {
340  case VR_LT:
341  goto pinf;
342  case VR_GT:
343  goto minf;
344  default:
345  goto inf_mul_zero;
346  }
347  }
348  else if (is_pinf<From2_Policy>(y)) {
349  switch (sgn<From1_Policy>(x)) {
350  case VR_LT:
351  minf:
352  return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
353  case VR_GT:
354  pinf:
355  return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
356  default:
357  inf_mul_zero:
358  PPL_ASSERT(To_Policy::check_inf_mul_zero);
359  return assign_nan<To_Policy>(to, V_INF_MUL_ZERO);
360  }
361  }
362  else {
363  native:
364  return mul<To_Policy, From1_Policy, From2_Policy>(to, x, y, dir);
365  }
366  }
367 }
368 
369 
370 template <typename To_Policy, typename From1_Policy, typename From2_Policy,
371  typename To, typename From1, typename From2>
372 inline Result
373 add_mul_ext(To& to, const From1& x, const From2& y, Rounding_Dir dir) {
374  if (!ext_to_handle<To_Policy>(to)
375  && !ext_to_handle<From1_Policy>(x) && !ext_to_handle<From2_Policy>(y)) {
376  goto native;
377  }
378  if (is_nan<To_Policy>(to)
379  || is_nan<From1_Policy>(x) || is_nan<From2_Policy>(y)) {
380  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
381  }
382  if (is_minf<From1_Policy>(x)) {
383  switch (sgn_ext<From2_Policy>(y)) {
384  case VR_LT:
385  goto a_pinf;
386  case VR_GT:
387  goto a_minf;
388  default:
389  goto inf_mul_zero;
390  }
391  }
392  else if (is_pinf<From1_Policy>(x)) {
393  switch (sgn_ext<From2_Policy>(y)) {
394  case VR_LT:
395  goto a_minf;
396  case VR_GT:
397  goto a_pinf;
398  default:
399  goto inf_mul_zero;
400  }
401  }
402  else {
403  if (is_minf<From2_Policy>(y)) {
404  switch (sgn<From1_Policy>(x)) {
405  case VR_LT:
406  goto a_pinf;
407  case VR_GT:
408  goto a_minf;
409  default:
410  goto inf_mul_zero;
411  }
412  }
413  else if (is_pinf<From2_Policy>(y)) {
414  switch (sgn<From1_Policy>(x)) {
415  case VR_LT:
416  a_minf:
417  if (CHECK_P(To_Policy::check_inf_add_inf, is_pinf<To_Policy>(to))) {
418  goto inf_add_inf;
419  }
420  else {
421  goto minf;
422  }
423  case VR_GT:
424  a_pinf:
425  if (CHECK_P(To_Policy::check_inf_add_inf, is_minf<To_Policy>(to))) {
426  inf_add_inf:
427  return assign_nan<To_Policy>(to, V_INF_ADD_INF);
428  }
429  else {
430  goto pinf;
431  }
432  default:
433  inf_mul_zero:
434  PPL_ASSERT(To_Policy::check_inf_mul_zero);
435  return assign_nan<To_Policy>(to, V_INF_MUL_ZERO);
436  }
437  }
438  else {
439  if (is_minf<To_Policy>(to)) {
440  minf:
441  return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
442  }
443  if (is_pinf<To_Policy>(to)) {
444  pinf:
445  return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
446  }
447  native:
448  return add_mul<To_Policy, From1_Policy, From2_Policy>(to, x, y, dir);
449  }
450  }
451 }
452 
453 template <typename To_Policy, typename From1_Policy, typename From2_Policy,
454  typename To, typename From1, typename From2>
455 inline Result
456 sub_mul_ext(To& to, const From1& x, const From2& y, Rounding_Dir dir) {
457  if (!ext_to_handle<To_Policy>(to)
458  && !ext_to_handle<From1_Policy>(x) && !ext_to_handle<From2_Policy>(y)) {
459  goto native;
460  }
461  if (is_nan<To_Policy>(to)
462  || is_nan<From1_Policy>(x) || is_nan<From2_Policy>(y)) {
463  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
464  }
465  if (is_minf<From1_Policy>(x)) {
466  switch (sgn_ext<From2_Policy>(y)) {
467  case VR_LT:
468  goto a_pinf;
469  case VR_GT:
470  goto a_minf;
471  default:
472  goto inf_mul_zero;
473  }
474  }
475  else if (is_pinf<From1_Policy>(x)) {
476  switch (sgn_ext<From2_Policy>(y)) {
477  case VR_LT:
478  goto a_minf;
479  case VR_GT:
480  goto a_pinf;
481  default:
482  goto inf_mul_zero;
483  }
484  }
485  else {
486  if (is_minf<From2_Policy>(y)) {
487  switch (sgn<From1_Policy>(x)) {
488  case VR_LT:
489  goto a_pinf;
490  case VR_GT:
491  goto a_minf;
492  default:
493  goto inf_mul_zero;
494  }
495  }
496  else if (is_pinf<From2_Policy>(y)) {
497  switch (sgn<From1_Policy>(x)) {
498  case VR_LT:
499  a_minf:
500  if (CHECK_P(To_Policy::check_inf_sub_inf, is_minf<To_Policy>(to))) {
501  goto inf_sub_inf;
502  }
503  else {
504  goto pinf;
505  }
506  case VR_GT:
507  a_pinf:
508  if (CHECK_P(To_Policy::check_inf_sub_inf, is_pinf<To_Policy>(to))) {
509  inf_sub_inf:
510  return assign_nan<To_Policy>(to, V_INF_SUB_INF);
511  }
512  else {
513  goto minf;
514  }
515  default:
516  inf_mul_zero:
517  PPL_ASSERT(To_Policy::check_inf_mul_zero);
518  return assign_nan<To_Policy>(to, V_INF_MUL_ZERO);
519  }
520  }
521  else {
522  if (is_minf<To_Policy>(to)) {
523  minf:
524  return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
525  }
526  if (is_pinf<To_Policy>(to)) {
527  pinf:
528  return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
529  }
530  native:
531  return sub_mul<To_Policy, From1_Policy, From2_Policy>(to, x, y, dir);
532  }
533  }
534 }
535 
536 template <typename To_Policy, typename From1_Policy, typename From2_Policy,
537  typename To, typename From1, typename From2>
538 inline Result
539 div_ext(To& to, const From1& x, const From2& y, Rounding_Dir dir) {
540  if (!ext_to_handle<From1_Policy>(x) && !ext_to_handle<From2_Policy>(y)) {
541  goto native;
542  }
543  if (is_nan<From1_Policy>(x) || is_nan<From2_Policy>(y)) {
544  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
545  }
546  if (is_minf<From1_Policy>(x)) {
547  if (CHECK_P(To_Policy::check_inf_div_inf, is_minf<From2_Policy>(y)
548  || is_pinf<From2_Policy>(y))) {
549  goto inf_div_inf;
550  }
551  else {
552  switch (sgn<From2_Policy>(y)) {
553  case VR_LT:
554  goto pinf;
555  case VR_GT:
556  goto minf;
557  default:
558  goto div_zero;
559  }
560  }
561  }
562  else if (is_pinf<From1_Policy>(x)) {
563  if (CHECK_P(To_Policy::check_inf_div_inf, is_minf<From2_Policy>(y)
564  || is_pinf<From2_Policy>(y))) {
565  inf_div_inf:
566  return assign_nan<To_Policy>(to, V_INF_DIV_INF);
567  }
568  else {
569  switch (sgn<From2_Policy>(y)) {
570  case VR_LT:
571  minf:
572  return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
573  case VR_GT:
574  pinf:
575  return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
576  default:
577  div_zero:
578  PPL_ASSERT(To_Policy::check_div_zero);
579  return assign_nan<To_Policy>(to, V_DIV_ZERO);
580  }
581  }
582  }
583  else {
584  if (is_minf<From2_Policy>(y) || is_pinf<From2_Policy>(y)) {
585  to = 0;
586  return V_EQ;
587  }
588  else {
589  native:
590  return div<To_Policy, From1_Policy, From2_Policy>(to, x, y, dir);
591  }
592  }
593 }
594 
595 
596 template <typename To_Policy, typename From1_Policy, typename From2_Policy,
597  typename To, typename From1, typename From2>
598 inline Result
599 idiv_ext(To& to, const From1& x, const From2& y, Rounding_Dir dir) {
600  if (!ext_to_handle<From1_Policy>(x) && !ext_to_handle<From2_Policy>(y)) {
601  goto native;
602  }
603  if (is_nan<From1_Policy>(x) || is_nan<From2_Policy>(y)) {
604  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
605  }
606  if (is_minf<From1_Policy>(x)) {
607  if (CHECK_P(To_Policy::check_inf_div_inf, is_minf<From2_Policy>(y)
608  || is_pinf<From2_Policy>(y))) {
609  goto inf_div_inf;
610  }
611  else {
612  switch (sgn<From2_Policy>(y)) {
613  case VR_LT:
614  goto pinf;
615  case VR_GT:
616  goto minf;
617  default:
618  goto div_zero;
619  }
620  }
621  }
622  else if (is_pinf<From1_Policy>(x)) {
623  if (CHECK_P(To_Policy::check_inf_div_inf, is_minf<From2_Policy>(y)
624  || is_pinf<From2_Policy>(y))) {
625  inf_div_inf:
626  return assign_nan<To_Policy>(to, V_INF_DIV_INF);
627  }
628  else {
629  switch (sgn<From2_Policy>(y)) {
630  case VR_LT:
631  minf:
632  return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
633  case VR_GT:
634  pinf:
635  return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
636  default:
637  div_zero:
638  PPL_ASSERT(To_Policy::check_div_zero);
639  return assign_nan<To_Policy>(to, V_DIV_ZERO);
640  }
641  }
642  }
643  else {
644  if (is_minf<From2_Policy>(y) || is_pinf<From2_Policy>(y)) {
645  to = 0;
646  return V_EQ;
647  }
648  else {
649  native:
650  return idiv<To_Policy, From1_Policy, From2_Policy>(to, x, y, dir);
651  }
652  }
653 }
654 
655 
656 template <typename To_Policy, typename From1_Policy, typename From2_Policy,
657  typename To, typename From1, typename From2>
658 inline Result
659 rem_ext(To& to, const From1& x, const From2& y, Rounding_Dir dir) {
660  if (!ext_to_handle<From1_Policy>(x) && !ext_to_handle<From2_Policy>(y)) {
661  goto native;
662  }
663  if (is_nan<From1_Policy>(x) || is_nan<From2_Policy>(y)) {
664  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
665  }
666  else if (CHECK_P(To_Policy::check_inf_mod, is_minf<From1_Policy>(x)
667  || is_pinf<From1_Policy>(x))) {
668  return assign_nan<To_Policy>(to, V_INF_MOD);
669  }
670  else {
671  if (is_minf<From1_Policy>(y) || is_pinf<From2_Policy>(y)) {
672  to = x;
673  return V_EQ;
674  }
675  else {
676  native:
677  return rem<To_Policy, From1_Policy, From2_Policy>(to, x, y, dir);
678  }
679  }
680 }
681 
682 template <typename To_Policy, typename From_Policy,
683  typename To, typename From>
684 inline Result
685 add_2exp_ext(To& to, const From& x, unsigned int exp, Rounding_Dir dir) {
686  if (!ext_to_handle<From_Policy>(x)) {
687  goto native;
688  }
689  if (is_nan<From_Policy>(x)) {
690  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
691  }
692  else if (is_minf<From_Policy>(x)) {
693  return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
694  }
695  else if (is_pinf<From_Policy>(x)) {
696  return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
697  }
698  else {
699  native:
700  return add_2exp<To_Policy, From_Policy>(to, x, exp, dir);
701  }
702 }
703 
704 template <typename To_Policy, typename From_Policy,
705  typename To, typename From>
706 inline Result
707 sub_2exp_ext(To& to, const From& x, unsigned int exp, Rounding_Dir dir) {
708  if (!ext_to_handle<From_Policy>(x)) {
709  goto native;
710  }
711  if (is_nan<From_Policy>(x)) {
712  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
713  }
714  else if (is_minf<From_Policy>(x)) {
715  return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
716  }
717  else if (is_pinf<From_Policy>(x)) {
718  return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
719  }
720  else {
721  native:
722  return sub_2exp<To_Policy, From_Policy>(to, x, exp, dir);
723  }
724 }
725 
726 template <typename To_Policy, typename From_Policy,
727  typename To, typename From>
728 inline Result
729 mul_2exp_ext(To& to, const From& x, unsigned int exp, Rounding_Dir dir) {
730  if (!ext_to_handle<From_Policy>(x)) {
731  goto native;
732  }
733  if (is_nan<From_Policy>(x)) {
734  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
735  }
736  else if (is_minf<From_Policy>(x)) {
737  return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
738  }
739  else if (is_pinf<From_Policy>(x)) {
740  return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
741  }
742  else {
743  native:
744  return mul_2exp<To_Policy, From_Policy>(to, x, exp, dir);
745  }
746 }
747 
748 template <typename To_Policy, typename From_Policy,
749  typename To, typename From>
750 inline Result
751 div_2exp_ext(To& to, const From& x, unsigned int exp, Rounding_Dir dir) {
752  if (!ext_to_handle<From_Policy>(x)) {
753  goto native;
754  }
755  if (is_nan<From_Policy>(x)) {
756  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
757  }
758  else if (is_minf<From_Policy>(x)) {
759  return assign_special<To_Policy>(to, VC_MINUS_INFINITY, dir);
760  }
761  else if (is_pinf<From_Policy>(x)) {
762  return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
763  }
764  else {
765  native:
766  return div_2exp<To_Policy, From_Policy>(to, x, exp, dir);
767  }
768 }
769 
770 template <typename To_Policy, typename From_Policy,
771  typename To, typename From>
772 inline Result
773 smod_2exp_ext(To& to, const From& x, unsigned int exp, Rounding_Dir dir) {
774  if (!ext_to_handle<From_Policy>(x)) {
775  goto native;
776  }
777  if (is_nan<From_Policy>(x)) {
778  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
779  }
780  else if (CHECK_P(To_Policy::check_inf_mod, is_minf<From_Policy>(x)
781  || is_pinf<From_Policy>(x))) {
782  return assign_nan<To_Policy>(to, V_INF_MOD);
783  }
784  else {
785  native:
786  return smod_2exp<To_Policy, From_Policy>(to, x, exp, dir);
787  }
788 }
789 
790 template <typename To_Policy, typename From_Policy,
791  typename To, typename From>
792 inline Result
793 umod_2exp_ext(To& to, const From& x, unsigned int exp, Rounding_Dir dir) {
794  if (!ext_to_handle<From_Policy>(x)) {
795  goto native;
796  }
797  if (is_nan<From_Policy>(x)) {
798  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
799  }
800  else if (CHECK_P(To_Policy::check_inf_mod, is_minf<From_Policy>(x)
801  || is_pinf<From_Policy>(x))) {
802  return assign_nan<To_Policy>(to, V_INF_MOD);
803  }
804  else {
805  native:
806  return umod_2exp<To_Policy, From_Policy>(to, x, exp, dir);
807  }
808 }
809 
810 template <typename To_Policy, typename From_Policy,
811  typename To, typename From>
812 inline Result
813 sqrt_ext(To& to, const From& x, Rounding_Dir dir) {
814  if (!ext_to_handle<From_Policy>(x)) {
815  goto native;
816  }
817  if (is_nan<From_Policy>(x)) {
818  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
819  }
820  else if (is_minf<From_Policy>(x)) {
821  return assign_nan<To_Policy>(to, V_SQRT_NEG);
822  }
823  else if (is_pinf<From_Policy>(x)) {
824  return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
825  }
826  else {
827  native:
828  return sqrt<To_Policy, From_Policy>(to, x, dir);
829  }
830 }
831 
832 template <typename To_Policy, typename From1_Policy, typename From2_Policy,
833  typename To, typename From1, typename From2>
834 inline Result
835 gcd_ext(To& to, const From1& x, const From2& y, Rounding_Dir dir) {
836  if (is_nan<From1_Policy>(x) || is_nan<From2_Policy>(y)) {
837  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
838  }
839  else if (is_minf<From1_Policy>(x) || is_pinf<From1_Policy>(x)) {
840  return abs_ext<To_Policy, From2_Policy>(to, y, dir);
841  }
842  else if (is_minf<From2_Policy>(y) || is_pinf<From2_Policy>(y)) {
843  return abs_ext<To_Policy, From1_Policy>(to, x, dir);
844  }
845  else {
846  return gcd<To_Policy, From1_Policy, From2_Policy>(to, x, y, dir);
847  }
848 }
849 
850 template <typename To1_Policy, typename To2_Policy, typename To3_Policy,
851  typename From1_Policy, typename From2_Policy,
852  typename To1, typename To2, typename To3,
853  typename From1, typename From2>
854 inline Result
855 gcdext_ext(To1& to, To2& s, To3& t, const From1& x, const From2& y,
856  Rounding_Dir dir) {
857  if (is_nan<From1_Policy>(x) || is_nan<From2_Policy>(y)) {
858  return assign_special<To1_Policy>(to, VC_NAN, ROUND_IGNORE);
859  }
860  else if (is_minf<From1_Policy>(x) || is_pinf<From1_Policy>(x)) {
861  s = 0;
862  t = y > 0 ? -1 : 1;
863  return abs_ext<To1_Policy, From2_Policy>(to, y, dir);
864  }
865  else if (is_minf<From2_Policy>(y) || is_pinf<From2_Policy>(y)) {
866  s = x > 0 ? -1 : 1;
867  t = 0;
868  return abs_ext<To1_Policy, From1_Policy>(to, x, dir);
869  }
870  else {
871  return gcdext<To1_Policy, To2_Policy, To3_Policy, From1_Policy, From2_Policy>(to, s, t, x, y, dir);
872  }
873 }
874 
875 template <typename To_Policy, typename From1_Policy, typename From2_Policy,
876  typename To, typename From1, typename From2>
877 inline Result
878 lcm_ext(To& to, const From1& x, const From2& y, Rounding_Dir dir) {
879  if (is_nan<From1_Policy>(x) || is_nan<From2_Policy>(y)) {
880  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
881  }
882  else if (is_minf<From1_Policy>(x) || is_pinf<From1_Policy>(x)
883  || is_minf<From2_Policy>(y) || is_pinf<From2_Policy>(y)) {
884  return assign_special<To_Policy>(to, VC_PLUS_INFINITY, dir);
885  }
886  else {
887  return lcm<To_Policy, From1_Policy, From2_Policy>(to, x, y, dir);
888  }
889 }
890 
891 template <typename Policy1, typename Policy2,
892  typename Type1, typename Type2>
893 inline Result_Relation
894 cmp_ext(const Type1& x, const Type2& y) {
895  if (!ext_to_handle<Policy1>(x) && !ext_to_handle<Policy2>(y)) {
896  goto native;
897  }
898  if (is_nan<Policy1>(x) || is_nan<Policy2>(y)) {
899  return VR_EMPTY;
900  }
901  else if (is_minf<Policy1>(x)) {
902  return is_minf<Policy2>(y) ? VR_EQ : VR_LT;
903  }
904  else if (is_pinf<Policy1>(x)) {
905  return is_pinf<Policy2>(y) ? VR_EQ : VR_GT;
906  }
907  else {
908  if (is_minf<Policy2>(y)) {
909  return VR_GT;
910  }
911  if (is_pinf<Policy2>(y)) {
912  return VR_LT;
913  }
914  native:
915  return cmp<Policy1, Policy2>(x, y);
916  }
917 }
918 
919 template <typename Policy1, typename Policy2,
920  typename Type1, typename Type2>
921 inline bool
922 lt_ext(const Type1& x, const Type2& y) {
923  if (!ext_to_handle<Policy1>(x) && !ext_to_handle<Policy2>(y)) {
924  goto native;
925  }
926  if (is_nan<Policy1>(x) || is_nan<Policy2>(y)) {
927  return false;
928  }
929  if (is_pinf<Policy1>(x) || is_minf<Policy2>(y)) {
930  return false;
931  }
932  if (is_minf<Policy1>(x) || is_pinf<Policy2>(y)) {
933  return true;
934  }
935  native:
936  return lt_p<Policy1, Policy2>(x, y);
937 }
938 
939 template <typename Policy1, typename Policy2,
940  typename Type1, typename Type2>
941 inline bool
942 gt_ext(const Type1& x, const Type2& y) {
943  return lt_ext<Policy1, Policy2>(y, x);
944 }
945 
946 template <typename Policy1, typename Policy2,
947  typename Type1, typename Type2>
948 inline bool
949 le_ext(const Type1& x, const Type2& y) {
950  if (!ext_to_handle<Policy1>(x) && !ext_to_handle<Policy2>(y)) {
951  goto native;
952  }
953  if (is_nan<Policy1>(x) || is_nan<Policy2>(y)) {
954  return false;
955  }
956  if (is_minf<Policy1>(x) || is_pinf<Policy2>(y)) {
957  return true;
958  }
959  if (is_pinf<Policy1>(x) || is_minf<Policy2>(y)) {
960  return false;
961  }
962  native:
963  return le_p<Policy1, Policy2>(x, y);
964 }
965 
966 template <typename Policy1, typename Policy2,
967  typename Type1, typename Type2>
968 inline bool
969 ge_ext(const Type1& x, const Type2& y) {
970  return le_ext<Policy1, Policy2>(y, x);
971 }
972 
973 template <typename Policy1, typename Policy2,
974  typename Type1, typename Type2>
975 inline bool
976 eq_ext(const Type1& x, const Type2& y) {
977  if (!ext_to_handle<Policy1>(x) && !ext_to_handle<Policy2>(y)) {
978  goto native;
979  }
980  if (is_nan<Policy1>(x) || is_nan<Policy2>(y)) {
981  return false;
982  }
983  if (is_minf<Policy1>(x)) {
984  return is_minf<Policy2>(y);
985  }
986  if (is_pinf<Policy1>(x)) {
987  return is_pinf<Policy2>(y);
988  }
989  else if (is_minf<Policy2>(y) || is_pinf<Policy2>(y)) {
990  return false;
991  }
992  native:
993  return eq_p<Policy1, Policy2>(x, y);
994 }
995 
996 template <typename Policy1, typename Policy2,
997  typename Type1, typename Type2>
998 inline bool
999 ne_ext(const Type1& x, const Type2& y) {
1000  return !eq_ext<Policy1, Policy2>(x, y);
1001 }
1002 
1003 template <typename Policy, typename Type>
1004 inline Result
1005 output_ext(std::ostream& os, const Type& x,
1006  const Numeric_Format& format, Rounding_Dir dir) {
1007  if (!ext_to_handle<Policy>(x)) {
1008  goto native;
1009  }
1010  if (is_nan<Policy>(x)) {
1011  os << "nan";
1012  return V_NAN;
1013  }
1014  if (is_minf<Policy>(x)) {
1015  os << "-inf";
1016  return V_EQ;
1017  }
1018  if (is_pinf<Policy>(x)) {
1019  os << "+inf";
1020  return V_EQ;
1021  }
1022  native:
1023  return output<Policy>(os, x, format, dir);
1024 }
1025 
1026 template <typename To_Policy, typename To>
1027 inline Result
1028 input_ext(To& to, std::istream& is, Rounding_Dir dir) {
1029  return input<To_Policy>(to, is, dir);
1030 }
1031 
1032 } // namespace Checked
1033 
1034 } // namespace Parma_Polyhedra_Library
1035 
1036 #endif // !defined(PPL_checked_ext_defs_hh)
Result gcd_ext(To &to, const From1 &x, const From2 &y, Rounding_Dir dir)
The computed result is exact.
Definition: Result_defs.hh:81
Taking the square root of a negative number.
Definition: Result_defs.hh:150
Result sub_mul_ext(To &to, const From1 &x, const From2 &y, Rounding_Dir dir)
Result lcm_ext(To &to, const From1 &x, const From2 &y, Rounding_Dir dir)
Result sqrt_ext(To &to, const From &x, Rounding_Dir dir)
Result sub_ext(To &to, const From1 &x, const From2 &y, Rounding_Dir dir)
Result mul_2exp_ext(To &to, const From &x, unsigned int exp, Rounding_Dir dir)
Rounding_Dir
Rounding directions for arithmetic computations.
Result construct_ext(To &to, const From &x, Rounding_Dir dir)
Result add_ext(To &to, const From1 &x, const From2 &y, Rounding_Dir dir)
Result
Possible outcomes of a checked arithmetic computation.
Definition: Result_defs.hh:76
From bool Type Type Rounding_Dir To
Result output_ext(std::ostream &os, const Type &x, const Numeric_Format &format, Rounding_Dir dir)
Result trunc_ext(To &to, const From &x, Rounding_Dir dir)
Result add_mul_ext(To &to, const From1 &x, const From2 &y, Rounding_Dir dir)
Negative infinity result class.
Definition: Result_defs.hh:34
Not a number result class.
Definition: Result_defs.hh:40
signed signed signed signed signed char signed signed signed signed signed int signed long long
Result neg_ext(To &to, const From &x, Rounding_Dir dir)
Not a number result.
Definition: Result_defs.hh:123
Result idiv_ext(To &to, const From1 &x, const From2 &y, Rounding_Dir dir)
Taking the modulus of an infinity.
Definition: Result_defs.hh:138
From bool Type Type Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir unsigned Rounding_Dir unsigned Rounding_Dir unsigned Rounding_Dir Rounding_Dir To2
Positive infinity result class.
Definition: Result_defs.hh:37
Result div_ext(To &to, const From1 &x, const From2 &y, Rounding_Dir dir)
Result mul_ext(To &to, const From1 &x, const From2 &y, Rounding_Dir dir)
A class holding a constant called value that evaluates to true.
Equal. This need to be accompanied by a value.
Definition: Result_defs.hh:51
Less than. This need to be accompanied by a value.
Definition: Result_defs.hh:54
From bool Type Type Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir unsigned Rounding_Dir unsigned Rounding_Dir unsigned Rounding_Dir Rounding_Dir To1
Result add_2exp_ext(To &to, const From &x, unsigned int exp, Rounding_Dir dir)
bool ne_ext(const Type1 &x, const Type2 &y)
bool eq_ext(const Type1 &x, const Type2 &y)
From bool Type Type Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir From1
Result ceil_ext(To &to, const From &x, Rounding_Dir dir)
Result sub_2exp_ext(To &to, const From &x, unsigned int exp, Rounding_Dir dir)
The entire library is confined to this namespace.
Definition: version.hh:61
Adding two infinities having opposite signs.
Definition: Result_defs.hh:132
Greater than. This need to be accompanied by a value.
Definition: Result_defs.hh:57
Result gcdext_ext(To1 &to, To2 &s, To3 &t, const From1 &x, const From2 &y, Rounding_Dir dir)
Result abs_ext(To &to, const From &x, Rounding_Dir dir)
From bool Type Type Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir From2
bool lt_ext(const Type1 &x, const Type2 &y)
Subtracting two infinities having the same sign.
Definition: Result_defs.hh:144
From bool Type Type Rounding_Dir From
Result cmp_ext(const Type1 &x, const Type2 &y)
No values satisfies the relation.
Definition: Result_defs.hh:48
Result input_ext(Type &x, std::istream &is, Rounding_Dir dir)
Result assign_ext(To &to, const From &from, Rounding_Dir dir)
Result smod_2exp_ext(To &to, const From &x, unsigned int exp, Rounding_Dir dir)
bool le_ext(const Type1 &x, const Type2 &y)
#define CHECK_P(cond, check)
bool gt_ext(const Type1 &x, const Type2 &y)
Multiplying an infinity by zero.
Definition: Result_defs.hh:141
A class holding a constant called value that evaluates to false.
From bool Type Type Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir Rounding_Dir unsigned Rounding_Dir unsigned Rounding_Dir unsigned Rounding_Dir Rounding_Dir To3
Result rem_ext(To &to, const From1 &x, const From2 &y, Rounding_Dir dir)
bool ge_ext(const Type1 &x, const Type2 &y)
Result div_2exp_ext(To &to, const From &x, unsigned int exp, Rounding_Dir dir)
Result umod_2exp_ext(To &to, const From &x, unsigned int exp, Rounding_Dir dir)
Result floor_ext(To &to, const From &x, Rounding_Dir dir)