Branch data Line data Source code
1 : : /* Conversion routines from GCC internal float representation to MPFR.
2 : : Copyright (C) 2010-2024 Free Software Foundation, Inc.
3 : :
4 : : This file is part of GCC.
5 : :
6 : : GCC is free software; you can redistribute it and/or modify it under
7 : : the terms of the GNU General Public License as published by the Free
8 : : Software Foundation; either version 3, or (at your option) any later
9 : : version.
10 : :
11 : : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 : : WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 : : for more details.
15 : :
16 : : You should have received a copy of the GNU General Public License
17 : : along with GCC; see the file COPYING3. If not see
18 : : <http://www.gnu.org/licenses/>. */
19 : :
20 : : #include "config.h"
21 : : #include "system.h"
22 : : #include "coretypes.h"
23 : : #include "tree.h"
24 : : #include "realmpfr.h"
25 : : #include "stor-layout.h"
26 : :
27 : : /* Convert from REAL_VALUE_TYPE to MPFR. The caller is responsible
28 : : for initializing and clearing the MPFR parameter. */
29 : :
30 : : void
31 : 626882 : mpfr_from_real (mpfr_ptr m, const REAL_VALUE_TYPE *r, mpfr_rnd_t rndmode)
32 : : {
33 : : /* We use a string as an intermediate type. */
34 : 626882 : char buf[128];
35 : 626882 : int ret;
36 : :
37 : : /* Take care of Infinity and NaN. */
38 : 626882 : if (r->cl == rvc_inf)
39 : : {
40 : 78 : mpfr_set_inf (m, r->sign == 1 ? -1 : 1);
41 : 211 : return;
42 : : }
43 : :
44 : 626804 : if (r->cl == rvc_nan)
45 : : {
46 : 55 : mpfr_set_nan (m);
47 : 55 : return;
48 : : }
49 : :
50 : 626749 : real_to_hexadecimal (buf, r, sizeof (buf), 0, 1);
51 : : /* mpfr_set_str() parses hexadecimal floats from strings in the same
52 : : format that GCC will output them. Nothing extra is needed. */
53 : 626749 : ret = mpfr_set_str (m, buf, 16, rndmode);
54 : 626749 : gcc_assert (ret == 0);
55 : : }
56 : :
57 : : /* Convert from MPFR to REAL_VALUE_TYPE, for a given format FORMAT and
58 : : rounding mode RNDMODE. FORMAT is only relevant if M is a NaN. */
59 : :
60 : : void
61 : 4269320 : real_from_mpfr (REAL_VALUE_TYPE *r, mpfr_srcptr m, const real_format *format,
62 : : mpfr_rnd_t rndmode)
63 : : {
64 : : /* We use a string as an intermediate type. */
65 : 4269320 : char buf[128], *rstr;
66 : 4269320 : mpfr_exp_t exp;
67 : :
68 : : /* Take care of Infinity and NaN. */
69 : 4269320 : if (mpfr_inf_p (m))
70 : : {
71 : 290 : *r = dconstinf;
72 : 290 : if (mpfr_sgn (m) < 0)
73 : 111 : *r = real_value_negate (r);
74 : 514 : return;
75 : : }
76 : :
77 : 4269030 : if (mpfr_nan_p (m))
78 : : {
79 : 224 : real_nan (r, "", 1, format);
80 : 224 : return;
81 : : }
82 : :
83 : 4268806 : rstr = mpfr_get_str (NULL, &exp, 16, 0, m, rndmode);
84 : :
85 : : /* The additional 12 chars add space for the sprintf below. This
86 : : leaves 6 digits for the exponent which is supposedly enough. */
87 : 4268806 : gcc_assert (rstr != NULL && strlen (rstr) < sizeof (buf) - 12);
88 : :
89 : : /* REAL_VALUE_ATOF expects the exponent for mantissa * 2**exp,
90 : : mpfr_get_str returns the exponent for mantissa * 16**exp, adjust
91 : : for that. */
92 : 4268806 : exp *= 4;
93 : :
94 : 4268806 : if (rstr[0] == '-')
95 : 83573 : sprintf (buf, "-0x.%sp%d", &rstr[1], (int) exp);
96 : : else
97 : 4185233 : sprintf (buf, "0x.%sp%d", rstr, (int) exp);
98 : :
99 : 4268806 : mpfr_free_str (rstr);
100 : :
101 : 4268806 : real_from_string (r, buf);
102 : : }
103 : :
104 : : /* Convert from MPFR to REAL_VALUE_TYPE, for a given type TYPE and rounding
105 : : mode RNDMODE. TYPE is only relevant if M is a NaN. */
106 : :
107 : : void
108 : 3924361 : real_from_mpfr (REAL_VALUE_TYPE *r, mpfr_srcptr m, tree type,
109 : : mpfr_rnd_t rndmode)
110 : : {
111 : 3924361 : real_from_mpfr (r, m, type ? REAL_MODE_FORMAT (TYPE_MODE (type)) : NULL,
112 : : rndmode);
113 : 3924361 : }
114 : :
|