/* Conversion routines from GCC internal float representation to MPFR.
   Copyright (C) 2010-2021 Free Software Foundation, Inc.

   This file is part of GCC.

   GCC is free software; you can redistribute it and/or modify it under
   the terms of the GNU General Public License as published by the Free
   Software Foundation; either version 3, or (at your option) any later
   version.

   GCC is distributed in the hope that it will be useful, but WITHOUT ANY
   WARRANTY; without even the implied warranty of MERCHANTABILITY or
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   for more details.

   You should have received a copy of the GNU General Public License
   along with GCC; see the file COPYING3.  If not see
   <http://www.gnu.org/licenses/>.  */

#include "config.h"
#include "system.h"
#include "coretypes.h"
#include "tree.h"
#include "realmpfr.h"
#include "stor-layout.h"

/* Convert from REAL_VALUE_TYPE to MPFR.  The caller is responsible
   for initializing and clearing the MPFR parameter.  */

void
mpfr_from_real (mpfr_ptr m, const REAL_VALUE_TYPE *r, mpfr_rnd_t rndmode)
{
  /* We use a string as an intermediate type.  */
  char buf[128];
  int ret;

  /* Take care of Infinity and NaN.  */
  if (r->cl == rvc_inf)
    {
      mpfr_set_inf (m, r->sign == 1 ? -1 : 1);
      return;
    }

  if (r->cl == rvc_nan)
    {
      mpfr_set_nan (m);
      return;
    }

  real_to_hexadecimal (buf, r, sizeof (buf), 0, 1);
  /* mpfr_set_str() parses hexadecimal floats from strings in the same
     format that GCC will output them.  Nothing extra is needed.  */
  ret = mpfr_set_str (m, buf, 16, rndmode);
  gcc_assert (ret == 0);
}

/* Convert from MPFR to REAL_VALUE_TYPE, for a given format FORMAT and
   rounding mode RNDMODE.  FORMAT is only relevant if M is a NaN.  */

void
real_from_mpfr (REAL_VALUE_TYPE *r, mpfr_srcptr m, const real_format *format,
		mpfr_rnd_t rndmode)
{
  /* We use a string as an intermediate type.  */
  char buf[128], *rstr;
  mpfr_exp_t exp;

  /* Take care of Infinity and NaN.  */
  if (mpfr_inf_p (m))
    {
      real_inf (r);
      if (mpfr_sgn (m) < 0)
	*r = real_value_negate (r);
      return;
    }

  if (mpfr_nan_p (m))
    {
      real_nan (r, "", 1, format);
      return;
    }

  rstr = mpfr_get_str (NULL, &exp, 16, 0, m, rndmode);

  /* The additional 12 chars add space for the sprintf below.  This
     leaves 6 digits for the exponent which is supposedly enough.  */
  gcc_assert (rstr != NULL && strlen (rstr) < sizeof (buf) - 12);

  /* REAL_VALUE_ATOF expects the exponent for mantissa * 2**exp,
     mpfr_get_str returns the exponent for mantissa * 16**exp, adjust
     for that.  */
  exp *= 4;

  if (rstr[0] == '-')
    sprintf (buf, "-0x.%sp%d", &rstr[1], (int) exp);
  else
    sprintf (buf, "0x.%sp%d", rstr, (int) exp);

  mpfr_free_str (rstr);

  real_from_string (r, buf);
}

/* Convert from MPFR to REAL_VALUE_TYPE, for a given type TYPE and rounding
   mode RNDMODE.  TYPE is only relevant if M is a NaN.  */

void
real_from_mpfr (REAL_VALUE_TYPE *r, mpfr_srcptr m, tree type,
		mpfr_rnd_t rndmode)
{
  real_from_mpfr (r, m, type ? REAL_MODE_FORMAT (TYPE_MODE (type)) : NULL,
		  rndmode);
}

