/* Compatibility functions for floating point formatting, reentrant versions.
   Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2004, 2006
   Free Software Foundation, Inc.
   This file is part of the GNU C Library.

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

   The GNU C Library 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
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
   02111-1307 USA.  */

#include <errno.h>
#include <float.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#include <stdlib.h>
#include <sys/param.h>
#include <math_ldbl_opt.h>

#ifndef FLOAT_TYPE
# define FLOAT_TYPE double
# define FUNC_PREFIX
# define FLOAT_FMT_FLAG
# define FLOAT_NAME_EXT
# define FLOAT_MIN_10_EXP DBL_MIN_10_EXP
# if DBL_MANT_DIG == 53
#  define NDIGIT_MAX 17
# elif DBL_MANT_DIG == 24
#  define NDIGIT_MAX 9
# elif DBL_MANT_DIG == 56
#  define NDIGIT_MAX 18
# else
/* See IEEE 854 5.6, table 2 for this formula.  Unfortunately we need a
   compile time constant here, so we cannot use it.  */
#  error "NDIGIT_MAX must be precomputed"
#  define NDIGIT_MAX (lrint (ceil (M_LN2 / M_LN10 * DBL_MANT_DIG + 1.0)))
# endif
# if DBL_MIN_10_EXP == -37
#  define FLOAT_MIN_10_NORM	1.0e-37
# elif DBL_MIN_10_EXP == -307
#  define FLOAT_MIN_10_NORM	1.0e-307
# elif DBL_MIN_10_EXP == -4931
#  define FLOAT_MIN_10_NORM	1.0e-4931
# else
/* libc can't depend on libm.  */
#  error "FLOAT_MIN_10_NORM must be precomputed"
#  define FLOAT_MIN_10_NORM	exp10 (DBL_MIN_10_EXP)
# endif
#else
# define LONG_DOUBLE_CVT
#endif

#define APPEND(a, b) APPEND2 (a, b)
#define APPEND2(a, b) a##b
#define __APPEND(a, b) __APPEND2 (a, b)
#define __APPEND2(a, b) __##a##b

#define FLOOR APPEND(floor, FLOAT_NAME_EXT)
#define FABS APPEND(fabs, FLOAT_NAME_EXT)
#define LOG10 APPEND(log10, FLOAT_NAME_EXT)
#define EXP APPEND(exp, FLOAT_NAME_EXT)


int
__APPEND (FUNC_PREFIX, fcvt_r) (value, ndigit, decpt, sign, buf, len)
     FLOAT_TYPE value;
     int ndigit, *decpt, *sign;
     char *buf;
     size_t len;
{
  ssize_t n;
  ssize_t i;
  int left;

  if (buf == NULL)
    {
      __set_errno (EINVAL);
      return -1;
    }

  left = 0;
  if (isfinite (value))
    {
      *sign = signbit (value) != 0;
      if (*sign)
	value = -value;

      if (ndigit < 0)
	{
	  /* Rounding to the left of the decimal point.  */
	  while (ndigit < 0)
	    {
	      FLOAT_TYPE new_value = value * 0.1;

	      if (new_value < 1.0)
		{
		  ndigit = 0;
		  break;
		}

	      value = new_value;
	      ++left;
	      ++ndigit;
	    }
	}
    }
  else
    /* Value is Inf or NaN.  */
    *sign = 0;

  n = __snprintf (buf, len, "%.*" FLOAT_FMT_FLAG "f", MIN (ndigit, NDIGIT_MAX),
		  value);
  /* Check for a too small buffer.  */
  if (n >= (ssize_t) len)
    return -1;

  i = 0;
  while (i < n && isdigit (buf[i]))
    ++i;
  *decpt = i;

  if (i == 0)
    /* Value is Inf or NaN.  */
    return 0;

  if (i < n)
    {
      do
	++i;
      while (i < n && !isdigit (buf[i]));

      if (*decpt == 1 && buf[0] == '0' && value != 0.0)
	{
	  /* We must not have leading zeroes.  Strip them all out and
	     adjust *DECPT if necessary.  */
	  --*decpt;
	  while (i < n && buf[i] == '0')
	    {
	      --*decpt;
	      ++i;
	    }
	}

      memmove (&buf[MAX (*decpt, 0)], &buf[i], n - i);
      buf[n - (i - MAX (*decpt, 0))] = '\0';
    }

  if (left)
    {
      *decpt += left;
      if ((ssize_t) --len > n)
	{
	  while (left-- > 0 && n < (ssize_t) len)
	    buf[n++] = '0';
	  buf[n] = '\0';
	}
    }

  return 0;
}

int
__APPEND (FUNC_PREFIX, ecvt_r) (value, ndigit, decpt, sign, buf, len)
     FLOAT_TYPE value;
     int ndigit, *decpt, *sign;
     char *buf;
     size_t len;
{
  int exponent = 0;

  if (isfinite (value) && value != 0.0)
    {
      /* Slow code that doesn't require -lm functions.  */
      FLOAT_TYPE d;
      FLOAT_TYPE f = 1.0;
      if (value < 0.0)
	d = -value;
      else
	d = value;
      /* For denormalized numbers the d < 1.0 case below won't work,
	 as f can overflow to +Inf.  */
      if (d < FLOAT_MIN_10_NORM)
	{
	  value /= FLOAT_MIN_10_NORM;
	  if (value < 0.0)
	    d = -value;
	  else
	    d = value;
	  exponent += FLOAT_MIN_10_EXP;
	}
      if (d < 1.0)
	{
	  do
	    {
	      f *= 10.0;
	      --exponent;
	    }
	  while (d * f < 1.0);

	  value *= f;
	}
      else if (d >= 10.0)
	{
	  do
	    {
	      f *= 10;
	      ++exponent;
	    }
	  while (d >= f * 10.0);

	  value /= f;
	}
    }
  else if (value == 0.0)
    /* SUSv2 leaves it unspecified whether *DECPT is 0 or 1 for 0.0.
       This could be changed to -1 if we want to return 0.  */
    exponent = 0;

  if (ndigit <= 0 && len > 0)
    {
      buf[0] = '\0';
      *decpt = 1;
      *sign = isfinite (value) ? signbit (value) != 0 : 0;
    }
  else
    if (__APPEND (FUNC_PREFIX, fcvt_r) (value, MIN (ndigit, NDIGIT_MAX) - 1,
					decpt, sign, buf, len))
      return -1;

  *decpt += exponent;
  return 0;
}

#if LONG_DOUBLE_COMPAT (libc, GLIBC_2_0)
# ifdef LONG_DOUBLE_CVT
#  define cvt_symbol(symbol) \
  cvt_symbol_1 (libc, __APPEND (FUNC_PREFIX, symbol), \
	      APPEND (FUNC_PREFIX, symbol), GLIBC_2_4)
#  define cvt_symbol_1(lib, local, symbol, version) \
    versioned_symbol (lib, local, symbol, version)
# else
#  define cvt_symbol(symbol) \
  cvt_symbol_1 (libc, __APPEND (FUNC_PREFIX, symbol), \
	      APPEND (q, symbol), GLIBC_2_0); \
  strong_alias (__APPEND (FUNC_PREFIX, symbol), APPEND (FUNC_PREFIX, symbol))
#  define cvt_symbol_1(lib, local, symbol, version) \
  compat_symbol (lib, local, symbol, version)
# endif
#else
# define cvt_symbol(symbol) \
  strong_alias (__APPEND (FUNC_PREFIX, symbol), APPEND (FUNC_PREFIX, symbol))
#endif
cvt_symbol(fcvt_r);
cvt_symbol(ecvt_r);
