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
handle_ext_natively(const T &)38 handle_ext_natively(const T&) {
39 return FPU_Related<T>::value;
40 }
41
42 template <typename Policy, typename Type>
43 inline bool
ext_to_handle(const Type & x)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
sgn_ext(const Type & x)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
construct_ext(To & to,const From & x,Rounding_Dir dir)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
assign_ext(To & to,const From & x,Rounding_Dir dir)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
neg_ext(To & to,const From & x,Rounding_Dir dir)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
floor_ext(To & to,const From & x,Rounding_Dir dir)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
ceil_ext(To & to,const From & x,Rounding_Dir dir)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
trunc_ext(To & to,const From & x,Rounding_Dir dir)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
abs_ext(To & to,const From & x,Rounding_Dir dir)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
add_ext(To & to,const From1 & x,const From2 & y,Rounding_Dir dir)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
sub_ext(To & to,const From1 & x,const From2 & y,Rounding_Dir dir)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
mul_ext(To & to,const From1 & x,const From2 & y,Rounding_Dir dir)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
add_mul_ext(To & to,const From1 & x,const From2 & y,Rounding_Dir dir)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
sub_mul_ext(To & to,const From1 & x,const From2 & y,Rounding_Dir dir)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
div_ext(To & to,const From1 & x,const From2 & y,Rounding_Dir dir)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
idiv_ext(To & to,const From1 & x,const From2 & y,Rounding_Dir dir)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
rem_ext(To & to,const From1 & x,const From2 & y,Rounding_Dir dir)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
add_2exp_ext(To & to,const From & x,unsigned int exp,Rounding_Dir dir)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
sub_2exp_ext(To & to,const From & x,unsigned int exp,Rounding_Dir dir)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
mul_2exp_ext(To & to,const From & x,unsigned int exp,Rounding_Dir dir)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
div_2exp_ext(To & to,const From & x,unsigned int exp,Rounding_Dir dir)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
smod_2exp_ext(To & to,const From & x,unsigned int exp,Rounding_Dir dir)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
umod_2exp_ext(To & to,const From & x,unsigned int exp,Rounding_Dir dir)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
sqrt_ext(To & to,const From & x,Rounding_Dir dir)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
gcd_ext(To & to,const From1 & x,const From2 & y,Rounding_Dir dir)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
gcdext_ext(To1 & to,To2 & s,To3 & t,const From1 & x,const From2 & y,Rounding_Dir dir)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
lcm_ext(To & to,const From1 & x,const From2 & y,Rounding_Dir dir)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
cmp_ext(const Type1 & x,const Type2 & y)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
lt_ext(const Type1 & x,const Type2 & y)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
gt_ext(const Type1 & x,const Type2 & y)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
le_ext(const Type1 & x,const Type2 & y)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
ge_ext(const Type1 & x,const Type2 & y)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
eq_ext(const Type1 & x,const Type2 & y)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
ne_ext(const Type1 & x,const Type2 & y)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
output_ext(std::ostream & os,const Type & x,const Numeric_Format & format,Rounding_Dir dir)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
input_ext(To & to,std::istream & is,Rounding_Dir dir)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)
1037