PPL  1.2
checked_float_inlines.hh
Go to the documentation of this file.
1 /* Specialized "checked" functions for native floating-point numbers.
2  Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it>
3  Copyright (C) 2010-2016 BUGSENG srl (http://bugseng.com)
4 
5 This file is part of the Parma Polyhedra Library (PPL).
6 
7 The PPL is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 The PPL is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
20 
21 For the most up-to-date information see the Parma Polyhedra Library
22 site: http://bugseng.com/products/ppl/ . */
23 
24 #ifndef PPL_checked_float_inlines_hh
25 #define PPL_checked_float_inlines_hh 1
26 
27 #include "compiler.hh"
28 #include <cmath>
29 
30 namespace Parma_Polyhedra_Library {
31 
32 namespace Checked {
33 
34 inline float
35 multiply_add(float x, float y, float z) {
36 #if PPL_HAVE_DECL_FMAF && defined(FP_FAST_FMAF) \
37  && !defined(__alpha) && !defined(__FreeBSD__)
38  return fmaf(x, y, z);
39 #else
40  return x*y + z;
41 #endif
42 }
43 
44 inline double
45 multiply_add(double x, double y, double z) {
46 #if PPL_HAVE_DECL_FMA && defined(FP_FAST_FMA) \
47  && !defined(__alpha) && !defined(__FreeBSD__)
48  return fma(x, y, z);
49 #else
50  return x*y + z;
51 #endif
52 }
53 
54 inline long double
55 multiply_add(long double x, long double y, long double z) {
56 #if PPL_HAVE_DECL_FMAL && defined(FP_FAST_FMAL) \
57  && !defined(__alpha) && !defined(__FreeBSD__)
58  return fmal(x, y, z);
59 #else
60  return x*y + z;
61 #endif
62 }
63 
64 #if PPL_HAVE_DECL_RINTF
65 inline float
66 round_to_integer(float x) {
67  return rintf(x);
68 }
69 #endif
70 
71 inline double
72 round_to_integer(double x) {
73  return rint(x);
74 }
75 
76 #if PPL_HAVE_DECL_RINTL
77 inline long double
78 round_to_integer(long double x) {
79  return rintl(x);
80 }
81 #elif !PPL_CXX_PROVIDES_PROPER_LONG_DOUBLE
82 // If proper long doubles are not provided, this is most likely
83 // because long double and double are the same type: use rint().
84 inline long double
85 round_to_integer(long double x) {
86  return rint(x);
87 }
88 #elif defined(__i386__) && (defined(__GNUC__) || defined(__INTEL_COMPILER))
89 // On Cygwin, we have proper long doubles but rintl() is not defined:
90 // luckily, one machine instruction is enough to save the day.
91 inline long double
92 round_to_integer(long double x) {
93  long double i;
94  __asm__ ("frndint" : "=t" (i) : "0" (x));
95  return i;
96 }
97 #endif
98 
99 inline bool
101  return round_direct(dir) || round_not_requested(dir);
102 }
103 
104 inline bool
106  return round_inverse(dir);
107 }
108 
109 // The FPU mode is "round down".
110 //
111 // The result of the rounded down multiplication is thus computed directly.
112 //
113 // a = 0.3
114 // b = 0.1
115 // c_i = a * b = 0.03
116 // c = c_i = 0.0
117 //
118 // To obtain the result of the rounded up multiplication
119 // we do -(-a * b).
120 //
121 // a = 0.3
122 // b = 0.1
123 // c_i = -a * b = -0.03
124 //
125 // Here c_i should be forced to lose excess precision, otherwise the
126 // FPU will truncate using the rounding mode in force, which is "round down".
127 //
128 // c_i = -c_i = 0.03
129 // c = c_i = 0.0
130 //
131 // Wrong result: we should have obtained c = 0.1.
132 
133 inline void
134 limit_precision(const float& v) {
135  PPL_CC_FLUSH(v);
136 }
137 
138 inline void
139 limit_precision(const double& v) {
140  PPL_CC_FLUSH(v);
141 }
142 
143 inline void
144 limit_precision(const long double&) {
145 }
146 
147 template <typename Policy, typename T>
148 inline Result
149 classify_float(const T v, bool nan, bool inf, bool sign) {
150  Float<T> f(v);
151  if ((nan || sign) && CHECK_P(Policy::has_nan, f.u.binary.is_nan())) {
152  return V_NAN;
153  }
154  if (inf) {
155  if (Policy::has_infinity) {
156  int sign_inf = f.u.binary.inf_sign();
157  if (sign_inf < 0) {
158  return V_EQ_MINUS_INFINITY;
159  }
160  if (sign_inf > 0) {
161  return V_EQ_PLUS_INFINITY;
162  }
163  }
164  else {
165  PPL_ASSERT(f.u.binary.inf_sign() == 0);
166  }
167  }
168  if (sign) {
169  if (v < 0) {
170  return V_LT;
171  }
172  if (v > 0) {
173  return V_GT;
174  }
175  return V_EQ;
176  }
177  return V_LGE;
178 }
179 
180 template <typename Policy, typename T>
181 inline bool
182 is_nan_float(const T v) {
183  Float<T> f(v);
184  return CHECK_P(Policy::has_nan, f.u.binary.is_nan());
185 }
186 
187 template <typename Policy, typename T>
188 inline bool
189 is_inf_float(const T v) {
190  Float<T> f(v);
191  return CHECK_P(Policy::has_infinity, (f.u.binary.inf_sign() != 0));
192 }
193 template <typename Policy, typename T>
194 inline bool
195 is_minf_float(const T v) {
196  Float<T> f(v);
197  return CHECK_P(Policy::has_infinity, (f.u.binary.inf_sign() < 0));
198 }
199 
200 template <typename Policy, typename T>
201 inline bool
202 is_pinf_float(const T v) {
203  Float<T> f(v);
204  return CHECK_P(Policy::has_infinity, (f.u.binary.inf_sign() > 0));
205 }
206 
207 
208 template <typename Policy, typename T>
209 inline bool
210 is_int_float(const T v) {
211  return round_to_integer(v) == v;
212 }
213 
214 template <typename Policy, typename T>
215 inline Result
217  PPL_ASSERT(c == VC_MINUS_INFINITY || c == VC_PLUS_INFINITY || c == VC_NAN);
218  switch (c) {
219  case VC_MINUS_INFINITY:
220  v = -HUGE_VAL;
221  return V_EQ_MINUS_INFINITY;
222  case VC_PLUS_INFINITY:
223  v = HUGE_VAL;
224  return V_EQ_PLUS_INFINITY;
225  case VC_NAN:
226  v = PPL_NAN;
227  return V_NAN;
228  default:
229  PPL_UNREACHABLE;
230  return V_NAN | V_UNREPRESENTABLE;
231  }
232 }
233 
234 template <typename T>
235 inline void
236 pred_float(T& v) {
237  Float<T> f(v);
238  PPL_ASSERT(!f.u.binary.is_nan());
239  PPL_ASSERT(f.u.binary.inf_sign() >= 0);
240  if (f.u.binary.zero_sign() > 0) {
241  f.u.binary.negate();
242  f.u.binary.inc();
243  }
244  else if (f.u.binary.sign_bit()) {
245  f.u.binary.inc();
246  }
247  else {
248  f.u.binary.dec();
249  }
250  v = f.value();
251 }
252 
253 template <typename T>
254 inline void
255 succ_float(T& v) {
256  Float<T> f(v);
257  PPL_ASSERT(!f.u.binary.is_nan());
258  PPL_ASSERT(f.u.binary.inf_sign() <= 0);
259  if (f.u.binary.zero_sign() < 0) {
260  f.u.binary.negate();
261  f.u.binary.inc();
262  }
263  else if (!f.u.binary.sign_bit()) {
264  f.u.binary.inc();
265  }
266  else {
267  f.u.binary.dec();
268  }
269  v = f.value();
270 }
271 
272 template <typename Policy, typename To>
273 inline Result
275  if (round_down(dir)) {
276  pred_float(to);
277  return V_GT;
278  }
279  return V_LT;
280 }
281 
282 template <typename Policy, typename To>
283 inline Result
285  if (round_up(dir)) {
286  succ_float(to);
287  return V_LT;
288  }
289  return V_GT;
290 }
291 
292 
293 template <typename Policy>
294 inline void
297  && !round_not_needed(dir) && round_strict_relation(dir)) {
299  }
300 }
301 
302 template <typename Policy>
303 inline Result
306  && !round_not_needed(dir) && round_strict_relation(dir)) {
307  switch (fpu_check_inexact()) {
308  case 0:
309  return V_EQ;
310  case -1:
311  goto unknown;
312  case 1:
313  break;
314  }
315  switch (round_dir(dir)) {
316  case ROUND_DOWN:
317  return V_GT;
318  case ROUND_UP:
319  return V_LT;
320  default:
321  return V_NE;
322  }
323  }
324  else {
325  unknown:
326  switch (round_dir(dir)) {
327  case ROUND_DOWN:
328  return V_GE;
329  case ROUND_UP:
330  return V_LE;
331  default:
332  return V_LGE;
333  }
334  }
335 }
336 
337 template <typename To_Policy, typename From_Policy, typename To, typename From>
338 inline Result
340  if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from)) {
341  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
342  }
343  to = from;
344  return V_EQ;
345 }
346 
347 template <typename To_Policy, typename From_Policy, typename To, typename From>
348 inline Result
350  if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from)) {
351  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
352  }
353  prepare_inexact<To_Policy>(dir);
354  if (fpu_direct_rounding(dir)) {
355  to = from;
356  }
357  else if (fpu_inverse_rounding(dir)) {
358  From tmp = -from;
359  to = tmp;
360  limit_precision(to);
361  to = -to;
362  }
363  else {
366  limit_precision(from);
367  to = from;
368  limit_precision(to);
370  }
371  return result_relation<To_Policy>(dir);
372 }
373 
374 template <typename To_Policy, typename From_Policy, typename To, typename From>
375 inline Result
376 assign_float_float(To& to, const From from, Rounding_Dir dir) {
377  if (sizeof(From) > sizeof(To)) {
378  return assign_float_float_inexact<To_Policy, From_Policy>(to, from, dir);
379  }
380  else {
381  return assign_float_float_exact<To_Policy, From_Policy>(to, from, dir);
382  }
383 }
384 
385 template <typename To_Policy, typename From_Policy, typename Type>
386 inline Result
387 floor_float(Type& to, const Type from, Rounding_Dir) {
388  if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from)) {
389  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
390  }
392  to = round_to_integer(from);
393  }
394  else if (fpu_inverse_rounding(ROUND_DOWN)) {
395  to = round_to_integer(-from);
396  limit_precision(to);
397  to = -to;
398  }
399  else {
402  limit_precision(from);
403  to = round_to_integer(from);
404  limit_precision(to);
406  }
407  return V_EQ;
408 }
409 
410 template <typename To_Policy, typename From_Policy, typename Type>
411 inline Result
412 ceil_float(Type& to, const Type from, Rounding_Dir) {
413  if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from)) {
414  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
415  }
417  to = round_to_integer(from);
418  }
419  else if (fpu_inverse_rounding(ROUND_UP)) {
420  to = round_to_integer(-from);
421  limit_precision(to);
422  to = -to;
423  }
424  else {
427  limit_precision(from);
428  to = round_to_integer(from);
429  limit_precision(to);
431  }
432  return V_EQ;
433 }
434 
435 template <typename To_Policy, typename From_Policy, typename Type>
436 inline Result
437 trunc_float(Type& to, const Type from, Rounding_Dir dir) {
438  if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from)) {
439  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
440  }
441  if (from >= 0) {
442  return floor<To_Policy, From_Policy>(to, from, dir);
443  }
444  else {
445  return ceil<To_Policy, From_Policy>(to, from, dir);
446  }
447 }
448 
449 template <typename To_Policy, typename From_Policy, typename Type>
450 inline Result
451 neg_float(Type& to, const Type from, Rounding_Dir) {
452  if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from)) {
453  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
454  }
455  to = -from;
456  return V_EQ;
457 }
458 
459 template <typename To_Policy, typename From1_Policy, typename From2_Policy,
460  typename Type>
461 inline Result
462 add_float(Type& to, const Type x, const Type y, Rounding_Dir dir) {
463  if (To_Policy::check_inf_add_inf
464  && is_inf_float<From1_Policy>(x) && x == -y) {
465  return assign_nan<To_Policy>(to, V_INF_ADD_INF);
466  }
467  prepare_inexact<To_Policy>(dir);
468  if (fpu_direct_rounding(dir)) {
469  to = x + y;
470  }
471  else if (fpu_inverse_rounding(dir)) {
472  to = -x - y;
473  limit_precision(to);
474  to = -to;
475  }
476  else {
479  limit_precision(x);
480  limit_precision(y);
481  to = x + y;
482  limit_precision(to);
484  }
485  if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to)) {
486  return V_NAN;
487  }
488  return result_relation<To_Policy>(dir);
489 }
490 
491 template <typename To_Policy, typename From1_Policy, typename From2_Policy,
492  typename Type>
493 inline Result
494 sub_float(Type& to, const Type x, const Type y, Rounding_Dir dir) {
495  if (To_Policy::check_inf_sub_inf
496  && is_inf_float<From1_Policy>(x) && x == y) {
497  return assign_nan<To_Policy>(to, V_INF_SUB_INF);
498  }
499  prepare_inexact<To_Policy>(dir);
500  if (fpu_direct_rounding(dir)) {
501  to = x - y;
502  }
503  else if (fpu_inverse_rounding(dir)) {
504  to = y - x;
505  limit_precision(to);
506  to = -to;
507  }
508  else {
511  limit_precision(x);
512  limit_precision(y);
513  to = x - y;
514  limit_precision(to);
516  }
517  if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to)) {
518  return V_NAN;
519  }
520  return result_relation<To_Policy>(dir);
521 }
522 
523 template <typename To_Policy, typename From1_Policy, typename From2_Policy,
524  typename Type>
525 inline Result
526 mul_float(Type& to, const Type x, const Type y, Rounding_Dir dir) {
527  if (To_Policy::check_inf_mul_zero
528  && ((x == 0 && is_inf_float<From2_Policy>(y))
529  ||
530  (y == 0 && is_inf_float<From1_Policy>(x)))) {
531  return assign_nan<To_Policy>(to, V_INF_MUL_ZERO);
532  }
533  prepare_inexact<To_Policy>(dir);
534  if (fpu_direct_rounding(dir)) {
535  to = x * y;
536  }
537  else if (fpu_inverse_rounding(dir)) {
538  to = x * -y;
539  limit_precision(to);
540  to = -to;
541  }
542  else {
545  limit_precision(x);
546  limit_precision(y);
547  to = x * y;
548  limit_precision(to);
550  }
551  if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to)) {
552  return V_NAN;
553  }
554  return result_relation<To_Policy>(dir);
555 }
556 
557 template <typename To_Policy, typename From1_Policy, typename From2_Policy,
558  typename Type>
559 inline Result
560 div_float(Type& to, const Type x, const Type y, Rounding_Dir dir) {
561  if (To_Policy::check_inf_div_inf
562  && is_inf_float<From1_Policy>(x) && is_inf_float<From2_Policy>(y)) {
563  return assign_nan<To_Policy>(to, V_INF_DIV_INF);
564  }
565  if (To_Policy::check_div_zero && y == 0) {
566  return assign_nan<To_Policy>(to, V_DIV_ZERO);
567  }
568  prepare_inexact<To_Policy>(dir);
569  if (fpu_direct_rounding(dir)) {
570  to = x / y;
571  }
572  else if (fpu_inverse_rounding(dir)) {
573  to = x / -y;
574  limit_precision(to);
575  to = -to;
576  }
577  else {
580  limit_precision(x);
581  limit_precision(y);
582  to = x / y;
583  limit_precision(to);
585  }
586  if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to)) {
587  return V_NAN;
588  }
589  return result_relation<To_Policy>(dir);
590 }
591 
592 template <typename To_Policy, typename From1_Policy, typename From2_Policy,
593  typename Type>
594 inline Result
595 idiv_float(Type& to, const Type x, const Type y, Rounding_Dir dir) {
596  Type temp;
597  // The inexact check is useless
598  dir = round_dir(dir);
599  Result r = div<To_Policy, From1_Policy, From2_Policy>(temp, x, y, dir);
600  if (result_class(r) != VC_NORMAL) {
601  to = temp;
602  return r;
603  }
604  Result r1 = trunc<To_Policy, To_Policy>(to, temp, ROUND_NOT_NEEDED);
605  PPL_ASSERT(r1 == V_EQ);
606  if (r == V_EQ || to != temp) {
607  return r1;
608  }
609  // FIXME: Prove that it is impossible to return a strict relation
610  return (dir == ROUND_UP) ? V_LE : V_GE;
611 }
612 
613 template <typename To_Policy, typename From1_Policy, typename From2_Policy,
614  typename Type>
615 inline Result
616 rem_float(Type& to, const Type x, const Type y, Rounding_Dir) {
617  if (To_Policy::check_inf_mod && is_inf_float<From1_Policy>(x)) {
618  return assign_nan<To_Policy>(to, V_INF_MOD);
619  }
620  if (To_Policy::check_div_zero && y == 0) {
621  return assign_nan<To_Policy>(to, V_MOD_ZERO);
622  }
623  to = std::fmod(x, y);
624  if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to)) {
625  return V_NAN;
626  }
627  return V_EQ;
628 }
629 
630 struct Float_2exp {
631  const_bool_nodef(has_nan, false);
632  const_bool_nodef(has_infinity, false);
633 };
634 
635 template <typename To_Policy, typename From_Policy, typename Type>
636 inline Result
637 add_2exp_float(Type& to, const Type x, unsigned int exp, Rounding_Dir dir) {
638  if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(x)) {
639  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
640  }
641  PPL_ASSERT(exp < sizeof_to_bits(sizeof(unsigned long long)));
642  return
643  add<To_Policy, From_Policy, Float_2exp>(to,
644  x,
645  Type(1ULL << exp),
646  dir);
647 }
648 
649 template <typename To_Policy, typename From_Policy, typename Type>
650 inline Result
651 sub_2exp_float(Type& to, const Type x, unsigned int exp, Rounding_Dir dir) {
652  if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(x)) {
653  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
654  }
655  PPL_ASSERT(exp < sizeof_to_bits(sizeof(unsigned long long)));
656  return
657  sub<To_Policy, From_Policy, Float_2exp>(to,
658  x,
659  Type(1ULL << exp),
660  dir);
661 }
662 
663 template <typename To_Policy, typename From_Policy, typename Type>
664 inline Result
665 mul_2exp_float(Type& to, const Type x, unsigned int exp, Rounding_Dir dir) {
666  if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(x)) {
667  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
668  }
669  PPL_ASSERT(exp < sizeof_to_bits(sizeof(unsigned long long)));
670  return
671  mul<To_Policy, From_Policy, Float_2exp>(to,
672  x,
673  Type(1ULL << exp),
674  dir);
675 }
676 
677 template <typename To_Policy, typename From_Policy, typename Type>
678 inline Result
679 div_2exp_float(Type& to, const Type x, unsigned int exp, Rounding_Dir dir) {
680  if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(x)) {
681  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
682  }
683  PPL_ASSERT(exp < sizeof_to_bits(sizeof(unsigned long long)));
684  return
685  div<To_Policy, From_Policy, Float_2exp>(to,
686  x,
687  Type(1ULL << exp),
688  dir);
689 }
690 
691 template <typename To_Policy, typename From_Policy, typename Type>
692 inline Result
693 smod_2exp_float(Type& to, const Type x, unsigned int exp, Rounding_Dir dir) {
694  if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(x)) {
695  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
696  }
697  if (To_Policy::check_inf_mod && is_inf_float<From_Policy>(x)) {
698  return assign_nan<To_Policy>(to, V_INF_MOD);
699  }
700  PPL_ASSERT(exp < sizeof_to_bits(sizeof(unsigned long long)));
701  Type m = 1ULL << exp;
702  rem_float<To_Policy, From_Policy, Float_2exp>(to, x, m, ROUND_IGNORE);
703  Type m2 = m / 2;
704  if (to < -m2) {
705  return add_float<To_Policy, From_Policy, Float_2exp>(to, to, m, dir);
706  }
707  else if (to >= m2) {
708  return sub_float<To_Policy, From_Policy, Float_2exp>(to, to, m, dir);
709  }
710  return V_EQ;
711 }
712 
713 template <typename To_Policy, typename From_Policy, typename Type>
714 inline Result
715 umod_2exp_float(Type& to, const Type x, unsigned int exp, Rounding_Dir dir) {
716  if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(x)) {
717  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
718  }
719  if (To_Policy::check_inf_mod && is_inf_float<From_Policy>(x)) {
720  return assign_nan<To_Policy>(to, V_INF_MOD);
721  }
722  PPL_ASSERT(exp < sizeof_to_bits(sizeof(unsigned long long)));
723  Type m = 1ULL << exp;
724  rem_float<To_Policy, From_Policy, Float_2exp>(to, x, m, ROUND_IGNORE);
725  if (to < 0) {
726  return add_float<To_Policy, From_Policy, Float_2exp>(to, to, m, dir);
727  }
728  return V_EQ;
729 }
730 
731 template <typename To_Policy, typename From_Policy, typename Type>
732 inline Result
733 abs_float(Type& to, const Type from, Rounding_Dir) {
734  if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from)) {
735  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
736  }
737  to = std::abs(from);
738  return V_EQ;
739 }
740 
741 template <typename To_Policy, typename From_Policy, typename Type>
742 inline Result
743 sqrt_float(Type& to, const Type from, Rounding_Dir dir) {
744  if (To_Policy::fpu_check_nan_result && is_nan<From_Policy>(from)) {
745  return assign_special<To_Policy>(to, VC_NAN, ROUND_IGNORE);
746  }
747  if (To_Policy::check_sqrt_neg && from < 0) {
748  return assign_nan<To_Policy>(to, V_SQRT_NEG);
749  }
750  prepare_inexact<To_Policy>(dir);
751  if (fpu_direct_rounding(dir)) {
752  to = std::sqrt(from);
753  }
754  else {
757  limit_precision(from);
758  to = std::sqrt(from);
759  limit_precision(to);
761  }
762  return result_relation<To_Policy>(dir);
763 }
764 
765 template <typename Policy, typename Type>
766 inline Result_Relation
767 sgn_float(const Type x) {
768  if (x > 0) {
769  return VR_GT;
770  }
771  if (x < 0) {
772  return VR_LT;
773  }
774  if (x == 0) {
775  return VR_EQ;
776  }
777  return VR_EMPTY;
778 }
779 
780 template <typename Policy1, typename Policy2, typename Type>
781 inline Result_Relation
782 cmp_float(const Type x, const Type y) {
783  if (x > y) {
784  return VR_GT;
785  }
786  if (x < y) {
787  return VR_LT;
788  }
789  if (x == y) {
790  return VR_EQ;
791  }
792  return VR_EMPTY;
793 }
794 
795 template <typename To_Policy, typename From_Policy, typename To, typename From>
796 inline Result
798  prepare_inexact<To_Policy>(dir);
799  if (fpu_direct_rounding(dir)) {
800  to = from;
801  }
802  else {
805  to = from;
806  limit_precision(to);
808  }
809  return result_relation<To_Policy>(dir);
810 }
811 
812 template <typename To_Policy, typename From_Policy, typename To, typename From>
813 inline Result
814 assign_float_int(To& to, const From from, Rounding_Dir dir) {
816  return assign_float_int_inexact<To_Policy, From_Policy>(to, from, dir);
817  }
818  else {
819  return assign_exact<To_Policy, From_Policy>(to, from, dir);
820  }
821 }
822 
823 template <typename Policy, typename T>
824 inline Result
826  switch (round_dir(dir)) {
827  case ROUND_UP:
828  {
829  Float<T> f;
830  f.u.binary.set_max(true);
831  to = f.value();
832  return V_LT_INF;
833  }
834  case ROUND_DOWN: // Fall through.
835  case ROUND_IGNORE:
836  to = -HUGE_VAL;
837  return V_GT_MINUS_INFINITY;
838  default:
839  PPL_UNREACHABLE;
840  return V_GT_MINUS_INFINITY;
841  }
842 }
843 
844 template <typename Policy, typename T>
845 inline Result
847  switch (round_dir(dir)) {
848  case ROUND_DOWN:
849  {
850  Float<T> f;
851  f.u.binary.set_max(false);
852  to = f.value();
853  return V_GT_SUP;
854  }
855  case ROUND_UP: // Fall through.
856  case ROUND_IGNORE:
857  to = HUGE_VAL;
858  return V_LT_PLUS_INFINITY;
859  default:
860  PPL_UNREACHABLE;
861  return V_LT_PLUS_INFINITY;
862  }
863 }
864 
865 template <typename To_Policy, typename From_Policy, typename T>
866 inline Result
867 assign_float_mpz(T& to, const mpz_class& from, Rounding_Dir dir) {
868  int sign = sgn(from);
869  if (sign == 0) {
870  to = 0;
871  return V_EQ;
872  }
873  mpz_srcptr from_z = from.get_mpz_t();
874  size_t exponent = mpz_sizeinbase(from_z, 2) - 1;
875  if (exponent > size_t(Float<T>::Binary::EXPONENT_MAX)) {
876  if (sign < 0) {
877  return set_neg_overflow_float<To_Policy>(to, dir);
878  }
879  else {
880  return set_pos_overflow_float<To_Policy>(to, dir);
881  }
882  }
883  unsigned long zeroes = mpn_scan1(from_z->_mp_d, 0);
884  size_t meaningful_bits = exponent - zeroes;
885  mpz_t mantissa;
886  mpz_init(mantissa);
887  if (exponent > Float<T>::Binary::MANTISSA_BITS) {
888  mpz_tdiv_q_2exp(mantissa,
889  from_z,
891  }
892  else {
893  mpz_mul_2exp(mantissa, from_z, Float<T>::Binary::MANTISSA_BITS - exponent);
894  }
895  Float<T> f;
896  f.u.binary.build(sign < 0, mantissa, static_cast<long>(exponent));
897  mpz_clear(mantissa);
898  to = f.value();
899  if (meaningful_bits > Float<T>::Binary::MANTISSA_BITS) {
900  if (sign < 0) {
901  return round_lt_float<To_Policy>(to, dir);
902  }
903  else {
904  return round_gt_float<To_Policy>(to, dir);
905  }
906  }
907  return V_EQ;
908 }
909 
910 template <typename To_Policy, typename From_Policy, typename T>
911 inline Result
912 assign_float_mpq(T& to, const mpq_class& from, Rounding_Dir dir) {
913  const mpz_class& numer = from.get_num();
914  const mpz_class& denom = from.get_den();
915  if (denom == 1) {
916  return assign_float_mpz<To_Policy, From_Policy>(to, numer, dir);
917  }
918  mpz_srcptr numer_z = numer.get_mpz_t();
919  mpz_srcptr denom_z = denom.get_mpz_t();
920  int sign = sgn(numer);
921  long exponent = static_cast<long>(mpz_sizeinbase(numer_z, 2))
922  - static_cast<long>(mpz_sizeinbase(denom_z, 2));
923  if (exponent < Float<T>::Binary::EXPONENT_MIN_DENORM) {
924  to = 0;
925  inexact:
926  if (sign < 0) {
927  return round_lt_float<To_Policy>(to, dir);
928  }
929  else {
930  return round_gt_float<To_Policy>(to, dir);
931  }
932  }
933  if (exponent > Float<T>::Binary::EXPONENT_MAX + 1) {
934  overflow:
935  if (sign < 0) {
936  return set_neg_overflow_float<To_Policy>(to, dir);
937  }
938  else {
939  return set_pos_overflow_float<To_Policy>(to, dir);
940  }
941  }
942  unsigned int needed_bits = Float<T>::Binary::MANTISSA_BITS + 1;
943  if (exponent < Float<T>::Binary::EXPONENT_MIN) {
944  long diff = Float<T>::Binary::EXPONENT_MIN - exponent;
945  needed_bits -= static_cast<unsigned int>(diff);
946  }
947  mpz_t mantissa;
948  mpz_init(mantissa);
949  {
950  long shift = static_cast<long>(needed_bits) - exponent;
951  if (shift > 0) {
952  mpz_mul_2exp(mantissa, numer_z, static_cast<unsigned long>(shift));
953  numer_z = mantissa;
954  }
955  else if (shift < 0) {
956  shift = -shift;
957  mpz_mul_2exp(mantissa, denom_z, static_cast<unsigned long>(shift));
958  denom_z = mantissa;
959  }
960  }
961  mpz_t r;
962  mpz_init(r);
963  mpz_tdiv_qr(mantissa, r, numer_z, denom_z);
964  size_t bits = mpz_sizeinbase(mantissa, 2);
965  bool inexact = (mpz_sgn(r) != 0);
966  mpz_clear(r);
967  if (bits == needed_bits + 1) {
968  inexact = (inexact || mpz_odd_p(mantissa));
969  mpz_tdiv_q_2exp(mantissa, mantissa, 1);
970  }
971  else {
972  --exponent;
973  }
974  if (exponent > Float<T>::Binary::EXPONENT_MAX) {
975  mpz_clear(mantissa);
976  goto overflow;
977  }
978  else if (exponent < Float<T>::Binary::EXPONENT_MIN - 1) {
979  // Denormalized.
980  exponent = Float<T>::Binary::EXPONENT_MIN - 1;
981  }
982  Float<T> f;
983  f.u.binary.build(sign < 0, mantissa, exponent);
984  mpz_clear(mantissa);
985  to = f.value();
986  if (inexact) {
987  goto inexact;
988  }
989  return V_EQ;
990 }
991 
992 template <typename To_Policy, typename From1_Policy, typename From2_Policy,
993  typename Type>
994 inline Result
995 add_mul_float(Type& to, const Type x, const Type y, Rounding_Dir dir) {
996  if (To_Policy::check_inf_mul_zero
997  && ((x == 0 && is_inf_float<From2_Policy>(y))
998  ||
999  (y == 0 && is_inf_float<From1_Policy>(x)))) {
1000  return assign_nan<To_Policy>(to, V_INF_MUL_ZERO);
1001  }
1002  // FIXME: missing check_inf_add_inf
1003  prepare_inexact<To_Policy>(dir);
1004  if (fpu_direct_rounding(dir)) {
1005  to = multiply_add(x, y, to);
1006  }
1007  else if (fpu_inverse_rounding(dir)) {
1008  to = multiply_add(-x, y, -to);
1009  limit_precision(to);
1010  to = -to;
1011  }
1012  else {
1015  limit_precision(x);
1016  limit_precision(y);
1017  limit_precision(to);
1018  to = multiply_add(x, y, to);
1019  limit_precision(to);
1021  }
1022  if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to)) {
1023  return V_NAN;
1024  }
1025  return result_relation<To_Policy>(dir);
1026 }
1027 
1028 template <typename To_Policy, typename From1_Policy, typename From2_Policy, typename Type>
1029 inline Result
1030 sub_mul_float(Type& to, const Type x, const Type y, Rounding_Dir dir) {
1031  if (To_Policy::check_inf_mul_zero
1032  && ((x == 0 && is_inf_float<From2_Policy>(y))
1033  ||
1034  (y == 0 && is_inf_float<From1_Policy>(x)))) {
1035  return assign_nan<To_Policy>(to, V_INF_MUL_ZERO);
1036  }
1037  // FIXME: missing check_inf_add_inf
1038  prepare_inexact<To_Policy>(dir);
1039  if (fpu_direct_rounding(dir)) {
1040  to = multiply_add(x, -y, to);
1041  }
1042  else if (fpu_inverse_rounding(dir)) {
1043  to = multiply_add(x, y, -to);
1044  limit_precision(to);
1045  to = -to;
1046  }
1047  else {
1050  limit_precision(x);
1051  limit_precision(y);
1052  limit_precision(to);
1053  to = multiply_add(x, -y, to);
1054  limit_precision(to);
1056  }
1057  if (To_Policy::fpu_check_nan_result && is_nan<To_Policy>(to)) {
1058  return V_NAN;
1059  }
1060  return result_relation<To_Policy>(dir);
1061 }
1062 
1063 template <typename From>
1064 inline void
1065 assign_mpq_numeric_float(mpq_class& to, const From from) {
1066  to = from;
1067 }
1068 
1069 template <>
1070 inline void
1071 assign_mpq_numeric_float(mpq_class& to, const long double from) {
1072  to = 0;
1073  if (from == 0.0L) {
1074  return;
1075  }
1076  mpz_class& num = to.get_num();
1077  mpz_class& den = to.get_den();
1078  int exp;
1079  long double n = std::frexp(from, &exp);
1080  bool neg = false;
1081  if (n < 0.0L) {
1082  neg = true;
1083  n = -n;
1084  }
1085  const long double mult = static_cast<long double>(ULONG_MAX) + 1.0L;
1086  const unsigned int bits = sizeof(unsigned long) * CHAR_BIT;
1087  while (true) {
1088  n *= mult;
1089  exp -= bits;
1090  const long double intpart = std::floor(n);
1091  num += static_cast<unsigned long>(intpart);
1092  n -= intpart;
1093  if (n == 0.0L) {
1094  break;
1095  }
1096  num <<= bits;
1097  }
1098  if (exp < 0) {
1099  den <<= -exp;
1100  }
1101  else {
1102  num <<= exp;
1103  }
1104  if (neg) {
1105  to = -to;
1106  }
1107  to.canonicalize();
1108 }
1109 
1110 template <typename Policy, typename Type>
1111 inline Result
1112 output_float(std::ostream& os, const Type from, const Numeric_Format&,
1113  Rounding_Dir) {
1114  if (from == 0) {
1115  os << "0";
1116  }
1117  else if (is_minf<Policy>(from)) {
1118  os << "-inf";
1119  }
1120  else if (is_pinf<Policy>(from)) {
1121  os << "+inf";
1122  }
1123  else if (is_nan<Policy>(from)) {
1124  os << "nan";
1125  }
1126  else {
1127  mpq_class q;
1128  assign_mpq_numeric_float(q, from);
1129  std::string s = float_mpq_to_string(q);
1130  os << s;
1131  }
1132  return V_EQ;
1133 }
1134 
1135 #if PPL_SUPPORTED_FLOAT
1137 #if PPL_SUPPORTED_DOUBLE
1140 #endif
1141 #if PPL_SUPPORTED_LONG_DOUBLE
1142 PPL_SPECIALIZE_ASSIGN(assign_float_float, float, long double)
1143 PPL_SPECIALIZE_ASSIGN(assign_float_float_exact, long double, float)
1144 #endif
1145 #endif
1146 
1147 #if PPL_SUPPORTED_DOUBLE
1148 PPL_SPECIALIZE_ASSIGN(assign_float_float_exact, double, double)
1149 #if PPL_SUPPORTED_LONG_DOUBLE
1150 PPL_SPECIALIZE_ASSIGN(assign_float_float, double, long double)
1151 PPL_SPECIALIZE_ASSIGN(assign_float_float_exact, long double, double)
1152 #endif
1153 #endif
1154 
1155 #if PPL_SUPPORTED_LONG_DOUBLE
1156 PPL_SPECIALIZE_ASSIGN(assign_float_float_exact, long double, long double)
1157 #endif
1158 
1159 #if PPL_SUPPORTED_FLOAT
1166 PPL_SPECIALIZE_ASSIGN(assign_float_int, float, signed char)
1167 PPL_SPECIALIZE_ASSIGN(assign_float_int, float, signed short)
1168 PPL_SPECIALIZE_ASSIGN(assign_float_int, float, signed int)
1169 PPL_SPECIALIZE_ASSIGN(assign_float_int, float, signed long)
1170 PPL_SPECIALIZE_ASSIGN(assign_float_int, float, signed long long)
1171 PPL_SPECIALIZE_ASSIGN(assign_float_int, float, unsigned char)
1172 PPL_SPECIALIZE_ASSIGN(assign_float_int, float, unsigned short)
1173 PPL_SPECIALIZE_ASSIGN(assign_float_int, float, unsigned int)
1174 PPL_SPECIALIZE_ASSIGN(assign_float_int, float, unsigned long)
1175 PPL_SPECIALIZE_ASSIGN(assign_float_int, float, unsigned long long)
1176 PPL_SPECIALIZE_ASSIGN(assign_float_mpz, float, mpz_class)
1177 PPL_SPECIALIZE_ASSIGN(assign_float_mpq, float, mpq_class)
1180 PPL_SPECIALIZE_FLOOR(floor_float, float, float)
1181 PPL_SPECIALIZE_CEIL(ceil_float, float, float)
1182 PPL_SPECIALIZE_TRUNC(trunc_float, float, float)
1183 PPL_SPECIALIZE_NEG(neg_float, float, float)
1184 PPL_SPECIALIZE_ABS(abs_float, float, float)
1185 PPL_SPECIALIZE_ADD(add_float, float, float, float)
1186 PPL_SPECIALIZE_SUB(sub_float, float, float, float)
1187 PPL_SPECIALIZE_MUL(mul_float, float, float, float)
1188 PPL_SPECIALIZE_DIV(div_float, float, float, float)
1189 PPL_SPECIALIZE_REM(rem_float, float, float, float)
1196 PPL_SPECIALIZE_SQRT(sqrt_float, float, float)
1197 PPL_SPECIALIZE_GCD(gcd_exact, float, float, float)
1198 PPL_SPECIALIZE_GCDEXT(gcdext_exact, float, float, float, float, float)
1199 PPL_SPECIALIZE_LCM(lcm_gcd_exact, float, float, float)
1201 PPL_SPECIALIZE_CMP(cmp_float, float, float)
1202 PPL_SPECIALIZE_ADD_MUL(add_mul_float, float, float, float)
1203 PPL_SPECIALIZE_SUB_MUL(sub_mul_float, float, float, float)
1206 #endif
1207 
1208 #if PPL_SUPPORTED_DOUBLE
1210 PPL_SPECIALIZE_IS_NAN(is_nan_float, double)
1211 PPL_SPECIALIZE_IS_MINF(is_minf_float, double)
1212 PPL_SPECIALIZE_IS_PINF(is_pinf_float, double)
1213 PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_float, double)
1214 PPL_SPECIALIZE_ASSIGN(assign_float_int, double, char)
1215 PPL_SPECIALIZE_ASSIGN(assign_float_int, double, signed char)
1216 PPL_SPECIALIZE_ASSIGN(assign_float_int, double, signed short)
1217 PPL_SPECIALIZE_ASSIGN(assign_float_int, double, signed int)
1218 PPL_SPECIALIZE_ASSIGN(assign_float_int, double, signed long)
1219 PPL_SPECIALIZE_ASSIGN(assign_float_int, double, signed long long)
1220 PPL_SPECIALIZE_ASSIGN(assign_float_int, double, unsigned char)
1221 PPL_SPECIALIZE_ASSIGN(assign_float_int, double, unsigned short)
1222 PPL_SPECIALIZE_ASSIGN(assign_float_int, double, unsigned int)
1223 PPL_SPECIALIZE_ASSIGN(assign_float_int, double, unsigned long)
1224 PPL_SPECIALIZE_ASSIGN(assign_float_int, double, unsigned long long)
1225 PPL_SPECIALIZE_ASSIGN(assign_float_mpz, double, mpz_class)
1226 PPL_SPECIALIZE_ASSIGN(assign_float_mpq, double, mpq_class)
1227 PPL_SPECIALIZE_COPY(copy_generic, double)
1228 PPL_SPECIALIZE_IS_INT(is_int_float, double)
1229 PPL_SPECIALIZE_FLOOR(floor_float, double, double)
1230 PPL_SPECIALIZE_CEIL(ceil_float, double, double)
1231 PPL_SPECIALIZE_TRUNC(trunc_float, double, double)
1232 PPL_SPECIALIZE_NEG(neg_float, double, double)
1233 PPL_SPECIALIZE_ABS(abs_float, double, double)
1234 PPL_SPECIALIZE_ADD(add_float, double, double, double)
1235 PPL_SPECIALIZE_SUB(sub_float, double, double, double)
1236 PPL_SPECIALIZE_MUL(mul_float, double, double, double)
1237 PPL_SPECIALIZE_DIV(div_float, double, double, double)
1238 PPL_SPECIALIZE_REM(rem_float, double, double, double)
1239 PPL_SPECIALIZE_ADD_2EXP(add_2exp_float, double, double)
1240 PPL_SPECIALIZE_SUB_2EXP(sub_2exp_float, double, double)
1241 PPL_SPECIALIZE_MUL_2EXP(mul_2exp_float, double, double)
1242 PPL_SPECIALIZE_DIV_2EXP(div_2exp_float, double, double)
1243 PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_float, double, double)
1244 PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_float, double, double)
1245 PPL_SPECIALIZE_SQRT(sqrt_float, double, double)
1246 PPL_SPECIALIZE_GCD(gcd_exact, double, double, double)
1247 PPL_SPECIALIZE_GCDEXT(gcdext_exact, double, double, double, double, double)
1248 PPL_SPECIALIZE_LCM(lcm_gcd_exact, double, double, double)
1249 PPL_SPECIALIZE_SGN(sgn_float, double)
1250 PPL_SPECIALIZE_CMP(cmp_float, double, double)
1251 PPL_SPECIALIZE_ADD_MUL(add_mul_float, double, double, double)
1252 PPL_SPECIALIZE_SUB_MUL(sub_mul_float, double, double, double)
1253 PPL_SPECIALIZE_INPUT(input_generic, double)
1254 PPL_SPECIALIZE_OUTPUT(output_float, double)
1255 #endif
1256 
1257 #if PPL_SUPPORTED_LONG_DOUBLE
1259 PPL_SPECIALIZE_IS_NAN(is_nan_float, long double)
1260 PPL_SPECIALIZE_IS_MINF(is_minf_float, long double)
1261 PPL_SPECIALIZE_IS_PINF(is_pinf_float, long double)
1262 PPL_SPECIALIZE_ASSIGN_SPECIAL(assign_special_float, long double)
1263 PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, char)
1264 PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, signed char)
1265 PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, signed short)
1266 PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, signed int)
1267 PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, signed long)
1268 PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, signed long long)
1269 PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, unsigned char)
1270 PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, unsigned short)
1271 PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, unsigned int)
1272 PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, unsigned long)
1273 PPL_SPECIALIZE_ASSIGN(assign_float_int, long double, unsigned long long)
1274 PPL_SPECIALIZE_ASSIGN(assign_float_mpz, long double, mpz_class)
1275 PPL_SPECIALIZE_ASSIGN(assign_float_mpq, long double, mpq_class)
1276 PPL_SPECIALIZE_COPY(copy_generic, long double)
1277 PPL_SPECIALIZE_IS_INT(is_int_float, long double)
1278 PPL_SPECIALIZE_FLOOR(floor_float, long double, long double)
1279 PPL_SPECIALIZE_CEIL(ceil_float, long double, long double)
1280 PPL_SPECIALIZE_TRUNC(trunc_float, long double, long double)
1281 PPL_SPECIALIZE_NEG(neg_float, long double, long double)
1282 PPL_SPECIALIZE_ABS(abs_float, long double, long double)
1283 PPL_SPECIALIZE_ADD(add_float, long double, long double, long double)
1284 PPL_SPECIALIZE_SUB(sub_float, long double, long double, long double)
1285 PPL_SPECIALIZE_MUL(mul_float, long double, long double, long double)
1286 PPL_SPECIALIZE_DIV(div_float, long double, long double, long double)
1287 PPL_SPECIALIZE_REM(rem_float, long double, long double, long double)
1288 PPL_SPECIALIZE_ADD_2EXP(add_2exp_float, long double, long double)
1289 PPL_SPECIALIZE_SUB_2EXP(sub_2exp_float, long double, long double)
1290 PPL_SPECIALIZE_MUL_2EXP(mul_2exp_float, long double, long double)
1291 PPL_SPECIALIZE_DIV_2EXP(div_2exp_float, long double, long double)
1292 PPL_SPECIALIZE_SMOD_2EXP(smod_2exp_float, long double, long double)
1293 PPL_SPECIALIZE_UMOD_2EXP(umod_2exp_float, long double, long double)
1294 PPL_SPECIALIZE_SQRT(sqrt_float, long double, long double)
1295 PPL_SPECIALIZE_GCD(gcd_exact, long double, long double, long double)
1296 PPL_SPECIALIZE_GCDEXT(gcdext_exact, long double, long double, long double,
1297  long double, long double)
1298 PPL_SPECIALIZE_LCM(lcm_gcd_exact, long double, long double, long double)
1299 PPL_SPECIALIZE_SGN(sgn_float, long double)
1300 PPL_SPECIALIZE_CMP(cmp_float, long double, long double)
1301 PPL_SPECIALIZE_ADD_MUL(add_mul_float, long double, long double, long double)
1302 PPL_SPECIALIZE_SUB_MUL(sub_mul_float, long double, long double, long double)
1303 PPL_SPECIALIZE_INPUT(input_generic, long double)
1304 PPL_SPECIALIZE_OUTPUT(output_float, long double)
1305 #endif
1306 
1307 } // namespace Checked
1308 
1309 } // namespace Parma_Polyhedra_Library
1310 
1311 #endif // !defined(PPL_checked_int_inlines_hh)
A positive integer overflow occurred (rounding down).
Definition: Result_defs.hh:108
Rounding_Dir round_dir(Rounding_Dir dir)
Result add_2exp_float(Type &to, const Type x, unsigned int exp, Rounding_Dir dir)
Result sub_float(Type &to, const Type x, const Type y, Rounding_Dir dir)
#define PPL_SPECIALIZE_NEG(func, To, From)
Result mul_float(Type &to, const Type x, const Type 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
bool fpu_direct_rounding(Rounding_Dir dir)
Result assign_float_mpq(T &to, const mpq_class &from, Rounding_Dir dir)
Result floor_float(Type &to, const Type from, Rounding_Dir)
#define PPL_SPECIALIZE_ADD_MUL(func, To, From1, From2)
#define PPL_SPECIALIZE_IS_MINF(func, Type)
Rounding_Dir
Rounding directions for arithmetic computations.
#define PPL_SPECIALIZE_SQRT(func, To, From)
A positive integer overflow occurred (rounding up).
Definition: Result_defs.hh:111
std::string float_mpq_to_string(mpq_class &q)
Definition: checked.cc:514
void assign_mpq_numeric_float(mpq_class &to, const From from)
Computing a remainder modulo zero.
Definition: Result_defs.hh:147
#define PPL_SPECIALIZE_CLASSIFY(func, Type)
#define PPL_SPECIALIZE_ADD(func, To, From1, From2)
float multiply_add(float x, float y, float z)
#define PPL_NAN
Definition: Float_defs.hh:41
bool round_strict_relation(Rounding_Dir dir)
Result
Possible outcomes of a checked arithmetic computation.
Definition: Result_defs.hh:76
From bool Type Type Rounding_Dir To
fpu_rounding_control_word_type fpu_save_rounding_direction(fpu_rounding_direction_type dir)
Sets the FPU rounding direction to dir and returns the rounding control word previously in use...
Result sub_2exp_float(Type &to, const Type x, unsigned int exp, Rounding_Dir dir)
Result neg_float(Type &to, const Type from, Rounding_Dir)
#define PPL_SPECIALIZE_REM(func, To, From1, From2)
int fpu_check_inexact()
Queries the inexact computation status.
Result classify_float(const T v, bool nan, bool inf, bool sign)
Negative infinity result class.
Definition: Result_defs.hh:34
Not a number result class.
Definition: Result_defs.hh:40
bool round_inverse(Rounding_Dir dir)
signed signed signed signed signed char signed signed signed signed signed int signed long long
Result gcdext_exact(To1 &to, To2 &s, To3 &t, const From1 &x, const From2 &y, Rounding_Dir dir)
#define PPL_SPECIALIZE_ABS(func, To, From)
Result trunc_float(Type &to, const Type from, Rounding_Dir dir)
Result input_generic(Type &to, std::istream &is, Rounding_Dir dir)
Result assign_float_int(To &to, const From from, Rounding_Dir dir)
#define PPL_SPECIALIZE_UMOD_2EXP(func, To, From)
Not a number result.
Definition: Result_defs.hh:123
Taking the modulus of an infinity.
Definition: Result_defs.hh:138
PPL_SPECIALIZE_GCDEXT(gcdext_exact, char, char, char, char, char) PPL_SPECIALIZE_GCDEXT(gcdext_exact
The computed result is inexact and rounded down.
Definition: Result_defs.hh:87
Result mul_2exp_float(Type &to, const Type x, unsigned int exp, Rounding_Dir dir)
#define PPL_SPECIALIZE_TRUNC(func, To, From)
Result assign_float_mpz(T &to, const mpz_class &from, Rounding_Dir dir)
#define PPL_SPECIALIZE_CMP(func, Type1, Type2)
#define PPL_SPECIALIZE_CEIL(func, To, From)
Result idiv_float(Type &to, const Type x, const Type y, Rounding_Dir dir)
#define PPL_SPECIALIZE_DIV(func, To, From1, From2)
#define PPL_SPECIALIZE_MUL_2EXP(func, To, From)
Positive infinity result class.
Definition: Result_defs.hh:37
Result div_float(Type &to, const Type x, const Type y, Rounding_Dir dir)
fpu_rounding_direction_type round_fpu_dir(Rounding_Dir dir)
bool round_not_needed(Rounding_Dir dir)
Result_Class result_class(Result r)
The computed result is not representable.
Definition: Result_defs.hh:159
Representable number result class.
Definition: Result_defs.hh:31
#define PPL_SPECIALIZE_SUB(func, To, From1, From2)
#define PPL_SPECIALIZE_ASSIGN_SPECIAL(func, Type)
#define sizeof_to_bits(size)
Definition: compiler.hh:80
Equal. This need to be accompanied by a value.
Definition: Result_defs.hh:51
void fpu_reset_inexact()
Clears the inexact computation status.
Less than. This need to be accompanied by a value.
Definition: Result_defs.hh:54
Result gcd_exact(To &to, const From1 &x, const From2 &y, Rounding_Dir dir)
The computed result is inexact.
Definition: Result_defs.hh:90
bool round_up(Rounding_Dir dir)
#define PPL_SPECIALIZE_ADD_2EXP(func, To, From)
Result set_pos_overflow_float(T &to, Rounding_Dir dir)
#define PPL_SPECIALIZE_GCD(func, To, From1, From2)
Result assign_float_int_inexact(To &to, const From from, Rounding_Dir dir)
#define PPL_SPECIALIZE_SUB_MUL(func, To, From1, From2)
Result rem_float(Type &to, const Type x, const Type y, Rounding_Dir)
void PPL_CC_FLUSH(const T &x)
No-op function that force the compiler to store the argument and to reread it from memory if needed (...
Definition: compiler.hh:49
Result assign_float_float_inexact(To &to, const From from, Rounding_Dir dir)
void fpu_restore_rounding_direction(fpu_rounding_control_word_type)
Restores the FPU rounding rounding control word to cw.
The computed result may be inexact and rounded up.
Definition: Result_defs.hh:93
#define PPL_SPECIALIZE_IS_INT(func, Type)
#define PPL_SPECIALIZE_FLOOR(func, To, From)
Result output_float(std::ostream &os, const Type from, const Numeric_Format &, Rounding_Dir)
Result sqrt_float(Type &to, const Type from, 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
#define PPL_SPECIALIZE_DIV_2EXP(func, To, From)
Result div_2exp_float(Type &to, const Type x, unsigned int exp, Rounding_Dir dir)
Result umod_2exp_float(Type &to, const Type x, unsigned int exp, Rounding_Dir dir)
Result sub_mul_float(Type &to, const Type x, const Type y, Rounding_Dir dir)
Greater than. This need to be accompanied by a value.
Definition: Result_defs.hh:57
Result_Relation cmp_float(const Type x, const Type y)
Enable_If< Is_Same< To_Policy, From_Policy >::value, void >::type copy_generic(Type &to, const Type &from)
Result add_float(Type &to, const Type x, const Type y, Rounding_Dir dir)
bool round_direct(Rounding_Dir dir)
The computed result may be inexact and rounded down.
Definition: Result_defs.hh:96
Subtracting two infinities having the same sign.
Definition: Result_defs.hh:144
Result round_gt_float(To &to, Rounding_Dir dir)
Result round_lt_float(To &to, Rounding_Dir dir)
Result_Relation sgn_float(const Type x)
From bool Type Type Rounding_Dir From
bool fpu_inverse_rounding(Rounding_Dir dir)
#define PPL_SPECIALIZE_IS_NAN(func, Type)
No values satisfies the relation.
Definition: Result_defs.hh:48
int sgn(Boundary_Type type, const T &x, const Info &info)
Result lcm_gcd_exact(To &to, const From1 &x, const From2 &y, Rounding_Dir dir)
#define PPL_SPECIALIZE_ASSIGN(func, To, From)
Result assign_float_float_exact(To &to, const From from, Rounding_Dir)
Result ceil_float(Type &to, const Type from, Rounding_Dir)
Result abs_float(Type &to, const Type from, Rounding_Dir)
#define PPL_SPECIALIZE_SUB_2EXP(func, To, From)
Result smod_2exp_float(Type &to, const Type x, unsigned int exp, Rounding_Dir dir)
#define PPL_SPECIALIZE_COPY(func, Type)
Result assign_special_float(T &v, Result_Class c, Rounding_Dir)
A negative integer overflow occurred (rounding down).
Definition: Result_defs.hh:114
Coefficient c
Definition: PIP_Tree.cc:64
#define PPL_SPECIALIZE_LCM(func, To, From1, From2)
Result assign_float_float(To &to, const From from, Rounding_Dir dir)
#define CHECK_P(cond, check)
#define PPL_SPECIALIZE_OUTPUT(func, Type)
The computed result is inexact and rounded up.
Definition: Result_defs.hh:84
The computed result may be inexact.
Definition: Result_defs.hh:99
Multiplying an infinity by zero.
Definition: Result_defs.hh:141
#define PPL_SPECIALIZE_INPUT(func, Type)
bool round_down(Rounding_Dir dir)
#define PPL_SPECIALIZE_SMOD_2EXP(func, To, From)
bool round_not_requested(Rounding_Dir dir)
A negative integer overflow occurred (rounding up).
Definition: Result_defs.hh:105
#define PPL_SPECIALIZE_MUL(func, To, From1, From2)
#define PPL_SPECIALIZE_IS_PINF(func, Type)
#define PPL_SPECIALIZE_SGN(func, From)
Result set_neg_overflow_float(T &to, Rounding_Dir dir)
Result add_mul_float(Type &to, const Type x, const Type y, Rounding_Dir dir)
Result result_relation(Rounding_Dir dir)