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