示例#1
0
__complex__ long double
cexpl (__complex__ long double x)
{
  __complex__ long double retval;

  if (FINITEL_P (__real__ x))
    {
      /* Real part is finite.  */
      if (FINITEL_P (__imag__ x))
	{
	  /* Imaginary part is finite.  */
	  long double exp_val = expl (__real__ x);
	  long double sinix = sinl (__imag__ x);
	  long double cosix = cosl (__imag__ x);

	  if (FINITEL_P (exp_val))
	    {
	      __real__ retval = exp_val * cosix;
	      __imag__ retval = exp_val * sinix;
	    }
	  else
	    {
	      __real__ retval = copysignl (exp_val, cosix);
	      __imag__ retval = copysignl (exp_val, sinix);
	    }
	}
      else
	{
	  /* If the imaginary part is +-inf or NaN and the real part
	     is not +-inf the result is NaN + iNaN.  */
	  __real__ retval = NAN;
	  __imag__ retval = NAN;
	}
    }
  else if (INFINITEL_P (__real__ x))
    {
      /* Real part is infinite.  */
      if (FINITEL_P (__imag__ x))
	{
	  /* Imaginary part is finite.  */
	  long double value = signbit (__real__ x) ? 0.0 : HUGE_VALL;

	  if (__imag__ x == 0.0)
	    {
	      /* Imaginary part is 0.0.  */
	      __real__ retval = value;
	      __imag__ retval = __imag__ x;
	    }
	  else
	    {
	      long double sinix = sinl (__imag__ x);
	      long double cosix = cosl (__imag__ x);

	      __real__ retval = copysignl (value, cosix);
	      __imag__ retval = copysignl (value, sinix);
	    }
	}
      else if (signbit (__real__ x) == 0)
	{
	  __real__ retval = HUGE_VALL;
	  __imag__ retval = NAN;
	}
      else
	{
	  __real__ retval = 0.0;
	  __imag__ retval = copysignl (0.0, __imag__ x);
	}
    }
  else
    {
      /* If the real part is NaN the result is NaN + iNaN.  */
      __real__ retval = NAN;
      __imag__ retval = NAN;
    }

  return retval;
}
示例#2
0
TEST(math, copysignl) {
  ASSERT_DOUBLE_EQ(0.0L, copysignl(0.0L, 1.0L));
  ASSERT_DOUBLE_EQ(-0.0L, copysignl(0.0L, -1.0L));
  ASSERT_DOUBLE_EQ(2.0L, copysignl(2.0L, 1.0L));
  ASSERT_DOUBLE_EQ(-2.0L, copysignl(2.0L, -1.0L));
}
示例#3
0
文件: cprojl.c 项目: KGG814/AOS
long double complex cprojl(long double complex z)
{
	if (isinf(creall(z)) || isinf(cimagl(z)))
		return cpackl(INFINITY, copysignl(0.0, creall(z)));
	return z;
}
示例#4
0
文件: s_fmal.c 项目: bingos/bitrig
/*
 * Fused multiply-add: Compute x * y + z with a single rounding error.
 *
 * We use scaling to avoid overflow/underflow, along with the
 * canonical precision-doubling technique adapted from:
 *
 *	Dekker, T.  A Floating-Point Technique for Extending the
 *	Available Precision.  Numer. Math. 18, 224-242 (1971).
 */
long double
fmal(long double x, long double y, long double z)
{
#if LDBL_MANT_DIG == 64
	static const long double split = 0x1p32L + 1.0;
#elif LDBL_MANT_DIG == 113
	static const long double split = 0x1p57L + 1.0;
#endif
	long double xs, ys, zs;
	long double c, cc, hx, hy, p, q, tx, ty;
	long double r, rr, s;
	int oround;
	int ex, ey, ez;
	int spread;

	/*
	 * Handle special cases. The order of operations and the particular
	 * return values here are crucial in handling special cases involving
	 * infinities, NaNs, overflows, and signed zeroes correctly.
	 */
	if (x == 0.0 || y == 0.0)
		return (x * y + z);
	if (z == 0.0)
		return (x * y);
	if (!isfinite(x) || !isfinite(y))
		return (x * y + z);
	if (!isfinite(z))
		return (z);

	xs = frexpl(x, &ex);
	ys = frexpl(y, &ey);
	zs = frexpl(z, &ez);
	oround = fegetround();
	spread = ex + ey - ez;

	/*
	 * If x * y and z are many orders of magnitude apart, the scaling
	 * will overflow, so we handle these cases specially.  Rounding
	 * modes other than FE_TONEAREST are painful.
	 */
	if (spread > LDBL_MANT_DIG * 2) {
		fenv_t env;
		feraiseexcept(FE_INEXACT);
		switch(oround) {
		case FE_TONEAREST:
			return (x * y);
		case FE_TOWARDZERO:
			if (x > 0.0 ^ y < 0.0 ^ z < 0.0)
				return (x * y);
			feholdexcept(&env);
			r = x * y;
			if (!fetestexcept(FE_INEXACT))
				r = nextafterl(r, 0);
			feupdateenv(&env);
			return (r);
		case FE_DOWNWARD:
			if (z > 0.0)
				return (x * y);
			feholdexcept(&env);
			r = x * y;
			if (!fetestexcept(FE_INEXACT))
				r = nextafterl(r, -INFINITY);
			feupdateenv(&env);
			return (r);
		default:	/* FE_UPWARD */
			if (z < 0.0)
				return (x * y);
			feholdexcept(&env);
			r = x * y;
			if (!fetestexcept(FE_INEXACT))
				r = nextafterl(r, INFINITY);
			feupdateenv(&env);
			return (r);
		}
	}
	if (spread < -LDBL_MANT_DIG) {
		feraiseexcept(FE_INEXACT);
		if (!isnormal(z))
			feraiseexcept(FE_UNDERFLOW);
		switch (oround) {
		case FE_TONEAREST:
			return (z);
		case FE_TOWARDZERO:
			if (x > 0.0 ^ y < 0.0 ^ z < 0.0)
				return (z);
			else
				return (nextafterl(z, 0));
		case FE_DOWNWARD:
			if (x > 0.0 ^ y < 0.0)
				return (z);
			else
				return (nextafterl(z, -INFINITY));
		default:	/* FE_UPWARD */
			if (x > 0.0 ^ y < 0.0)
				return (nextafterl(z, INFINITY));
			else
				return (z);
		}
	}

	/*
	 * Use Dekker's algorithm to perform the multiplication and
	 * subsequent addition in twice the machine precision.
	 * Arrange so that x * y = c + cc, and x * y + z = r + rr.
	 */
	fesetround(FE_TONEAREST);

	p = xs * split;
	hx = xs - p;
	hx += p;
	tx = xs - hx;

	p = ys * split;
	hy = ys - p;
	hy += p;
	ty = ys - hy;

	p = hx * hy;
	q = hx * ty + tx * hy;
	c = p + q;
	cc = p - c + q + tx * ty;

	zs = ldexpl(zs, -spread);
	r = c + zs;
	s = r - c;
	rr = (c - (r - s)) + (zs - s) + cc;

	spread = ex + ey;
	if (spread + ilogbl(r) > -16383) {
		fesetround(oround);
		r = r + rr;
	} else {
		/*
		 * The result is subnormal, so we round before scaling to
		 * avoid double rounding.
		 */
		p = ldexpl(copysignl(0x1p-16382L, r), -spread);
		c = r + p;
		s = c - r;
		cc = (r - (c - s)) + (p - s) + rr;
		fesetround(oround);
		r = (c + cc) - p;
	}
	return (ldexpl(r, spread));
}
示例#5
0
文件: s_fmal.c 项目: michalsc/AROS
/*
 * Fused multiply-add: Compute x * y + z with a single rounding error.
 *
 * We use scaling to avoid overflow/underflow, along with the
 * canonical precision-doubling technique adapted from:
 *
 *	Dekker, T.  A Floating-Point Technique for Extending the
 *	Available Precision.  Numer. Math. 18, 224-242 (1971).
 */
long double
fmal(long double x, long double y, long double z)
{
	long double xs, ys, zs, adj;
	struct dd xy, r;
	int oround;
	int ex, ey, ez;
	int spread;

	/*
	 * Handle special cases. The order of operations and the particular
	 * return values here are crucial in handling special cases involving
	 * infinities, NaNs, overflows, and signed zeroes correctly.
	 */
	if (x == 0.0 || y == 0.0)
		return (x * y + z);
	if (z == 0.0)
		return (x * y);
	if (!isfinite(x) || !isfinite(y))
		return (x * y + z);
	if (!isfinite(z))
		return (z);

	xs = frexpl(x, &ex);
	ys = frexpl(y, &ey);
	zs = frexpl(z, &ez);
	oround = fegetround();
	spread = ex + ey - ez;

	/*
	 * If x * y and z are many orders of magnitude apart, the scaling
	 * will overflow, so we handle these cases specially.  Rounding
	 * modes other than FE_TONEAREST are painful.
	 */
	if (spread < -LDBL_MANT_DIG) {
		feraiseexcept(FE_INEXACT);
		if (!isnormal(z))
			feraiseexcept(FE_UNDERFLOW);
		switch (oround) {
		case FE_TONEAREST:
			return (z);
		case FE_TOWARDZERO:
			if (x > 0.0 ^ y < 0.0 ^ z < 0.0)
				return (z);
			else
				return (nextafterl(z, 0));
		case FE_DOWNWARD:
			if (x > 0.0 ^ y < 0.0)
				return (z);
			else
				return (nextafterl(z, -INFINITY));
		default:	/* FE_UPWARD */
			if (x > 0.0 ^ y < 0.0)
				return (nextafterl(z, INFINITY));
			else
				return (z);
		}
	}
	if (spread <= LDBL_MANT_DIG * 2)
		zs = ldexpl(zs, -spread);
	else
		zs = copysignl(LDBL_MIN, zs);

	fesetround(FE_TONEAREST);
	/* work around clang bug 8100 */
	volatile long double vxs = xs;

	/*
	 * Basic approach for round-to-nearest:
	 *
	 *     (xy.hi, xy.lo) = x * y		(exact)
	 *     (r.hi, r.lo)   = xy.hi + z	(exact)
	 *     adj = xy.lo + r.lo		(inexact; low bit is sticky)
	 *     result = r.hi + adj		(correctly rounded)
	 */
	xy = dd_mul(vxs, ys);
	r = dd_add(xy.hi, zs);

	spread = ex + ey;

	if (r.hi == 0.0) {
		/*
		 * When the addends cancel to 0, ensure that the result has
		 * the correct sign.
		 */
		fesetround(oround);
		volatile long double vzs = zs; /* XXX gcc CSE bug workaround */
		return (xy.hi + vzs + ldexpl(xy.lo, spread));
	}

	if (oround != FE_TONEAREST) {
		/*
		 * There is no need to worry about double rounding in directed
		 * rounding modes.
		 */
		fesetround(oround);
		/* work around clang bug 8100 */
		volatile long double vrlo = r.lo;
		adj = vrlo + xy.lo;
		return (ldexpl(r.hi + adj, spread));
	}

	adj = add_adjusted(r.lo, xy.lo);
	if (spread + ilogbl(r.hi) > -16383)
		return (ldexpl(r.hi + adj, spread));
	else
		return (add_and_denormalize(r.hi, adj, spread));
}
示例#6
0
TEST(math, copysignl) {
  ASSERT_FLOAT_EQ(0.0f, copysignl(0.0, 1.0));
  ASSERT_FLOAT_EQ(-0.0f, copysignl(0.0, -1.0));
  ASSERT_FLOAT_EQ(2.0f, copysignl(2.0, 1.0));
  ASSERT_FLOAT_EQ(-2.0f, copysignl(2.0, -1.0));
}
示例#7
0
static int testl(long double long_double_x, int int_x, long long_x)
{
int r = 0;
r += __finitel(long_double_x);
r += __fpclassifyl(long_double_x);
r += __isinfl(long_double_x);
r += __isnanl(long_double_x);
r += __signbitl(long_double_x);
r += acoshl(long_double_x);
r += acosl(long_double_x);
r += asinhl(long_double_x);
r += asinl(long_double_x);
r += atan2l(long_double_x, long_double_x);
r += atanhl(long_double_x);
r += atanl(long_double_x);
r += cbrtl(long_double_x);
r += ceill(long_double_x);
r += copysignl(long_double_x, long_double_x);
r += coshl(long_double_x);
r += cosl(long_double_x);
r += erfcl(long_double_x);
r += erfl(long_double_x);
r += exp2l(long_double_x);
r += expl(long_double_x);
r += expm1l(long_double_x);
r += fabsl(long_double_x);
r += fdiml(long_double_x, long_double_x);
r += floorl(long_double_x);
r += fmal(long_double_x, long_double_x, long_double_x);
r += fmaxl(long_double_x, long_double_x);
r += fminl(long_double_x, long_double_x);
r += fmodl(long_double_x, long_double_x);
r += frexpl(long_double_x, &int_x);
r += hypotl(long_double_x, long_double_x);
r += ilogbl(long_double_x);
r += ldexpl(long_double_x, int_x);
r += lgammal(long_double_x);
r += llrintl(long_double_x);
r += llroundl(long_double_x);
r += log10l(long_double_x);
r += log1pl(long_double_x);
r += log2l(long_double_x);
r += logbl(long_double_x);
r += logl(long_double_x);
r += lrintl(long_double_x);
r += lroundl(long_double_x);
r += modfl(long_double_x, &long_double_x);
r += nearbyintl(long_double_x);
r += nextafterl(long_double_x, long_double_x);
r += nexttowardl(long_double_x, long_double_x);
r += powl(long_double_x, long_double_x);
r += remainderl(long_double_x, long_double_x);
r += remquol(long_double_x, long_double_x, &int_x);
r += rintl(long_double_x);
r += roundl(long_double_x);
r += scalblnl(long_double_x, long_x);
r += scalbnl(long_double_x, int_x);
r += sinhl(long_double_x);
r += sinl(long_double_x);
r += sqrtl(long_double_x);
r += tanhl(long_double_x);
r += tanl(long_double_x);
r += tgammal(long_double_x);
r += truncl(long_double_x);
return r;
}
示例#8
0
DLLEXPORT long double complex
csqrtl(long double complex z)
{
	long double complex result;
	long double a, b;
	long double t;
	int scale;

	a = creall(z);
	b = cimagl(z);

	/* Handle special cases. */
	if (z == 0)
		return (CMPLXL(0, b));
	if (isinf(b))
		return (CMPLXL(INFINITY, b));
	if (isnan(a)) {
		t = (b - b) / (b - b);	/* raise invalid if b is not a NaN */
		return (CMPLXL(a, t));	/* return NaN + NaN i */
	}
	if (isinf(a)) {
		/*
		 * csqrt(inf + NaN i)  = inf +  NaN i
		 * csqrt(inf + y i)    = inf +  0 i
		 * csqrt(-inf + NaN i) = NaN +- inf i
		 * csqrt(-inf + y i)   = 0   +  inf i
		 */
		if (signbit(a))
			return (CMPLXL(fabsl(b - b), copysignl(a, b)));
		else
			return (CMPLXL(a, copysignl(b - b, b)));
	}
	/*
	 * The remaining special case (b is NaN) is handled just fine by
	 * the normal code path below.
	 */

	/* Scale to avoid overflow. */
	if (fabsl(a) >= THRESH || fabsl(b) >= THRESH) {
		a *= 0.25;
		b *= 0.25;
		scale = 1;
	} else {
		scale = 0;
	}

	/* Algorithm 312, CACM vol 10, Oct 1967. */
	if (a >= 0) {
		t = sqrtl((a + hypotl(a, b)) * 0.5);
		result = CMPLXL(t, b / (2 * t));
	} else {
		t = sqrtl((-a + hypotl(a, b)) * 0.5);
		result = CMPLXL(fabsl(b) / (2 * t), copysignl(t, b));
	}

	/* Rescale. */
	if (scale)
		return (result * 2);
	else
		return (result);
}
示例#9
0
文件: fmal.c 项目: 4ian/emscripten
/*
 * Fused multiply-add: Compute x * y + z with a single rounding error.
 *
 * We use scaling to avoid overflow/underflow, along with the
 * canonical precision-doubling technique adapted from:
 *
 *      Dekker, T.  A Floating-Point Technique for Extending the
 *      Available Precision.  Numer. Math. 18, 224-242 (1971).
 */
long double fmal(long double x, long double y, long double z)
{
	#pragma STDC FENV_ACCESS ON
	long double xs, ys, zs, adj;
	struct dd xy, r;
	int oround;
	int ex, ey, ez;
	int spread;

	/*
	 * Handle special cases. The order of operations and the particular
	 * return values here are crucial in handling special cases involving
	 * infinities, NaNs, overflows, and signed zeroes correctly.
	 */
	if (!isfinite(x) || !isfinite(y))
		return (x * y + z);
	if (!isfinite(z))
		return (z);
	if (x == 0.0 || y == 0.0)
		return (x * y + z);
	if (z == 0.0)
		return (x * y);

	xs = frexpl(x, &ex);
	ys = frexpl(y, &ey);
	zs = frexpl(z, &ez);
	oround = fegetround();
	spread = ex + ey - ez;

	/*
	 * If x * y and z are many orders of magnitude apart, the scaling
	 * will overflow, so we handle these cases specially.  Rounding
	 * modes other than FE_TONEAREST are painful.
	 */
	if (spread < -LDBL_MANT_DIG) {
#ifdef FE_INEXACT
		feraiseexcept(FE_INEXACT);
#endif
#ifdef FE_UNDERFLOW
		if (!isnormal(z))
			feraiseexcept(FE_UNDERFLOW);
#endif
		switch (oround) {
		default: /* FE_TONEAREST */
			return (z);
#ifdef FE_TOWARDZERO
		case FE_TOWARDZERO:
			if (x > 0.0 ^ y < 0.0 ^ z < 0.0)
				return (z);
			else
				return (nextafterl(z, 0));
#endif
#ifdef FE_DOWNWARD
		case FE_DOWNWARD:
			if (x > 0.0 ^ y < 0.0)
				return (z);
			else
				return (nextafterl(z, -INFINITY));
#endif
#ifdef FE_UPWARD
		case FE_UPWARD:
			if (x > 0.0 ^ y < 0.0)
				return (nextafterl(z, INFINITY));
			else
				return (z);
#endif
		}
	}
	if (spread <= LDBL_MANT_DIG * 2)
		zs = scalbnl(zs, -spread);
	else
		zs = copysignl(LDBL_MIN, zs);

	fesetround(FE_TONEAREST);

	/*
	 * Basic approach for round-to-nearest:
	 *
	 *     (xy.hi, xy.lo) = x * y           (exact)
	 *     (r.hi, r.lo)   = xy.hi + z       (exact)
	 *     adj = xy.lo + r.lo               (inexact; low bit is sticky)
	 *     result = r.hi + adj              (correctly rounded)
	 */
	xy = dd_mul(xs, ys);
	r = dd_add(xy.hi, zs);

	spread = ex + ey;

	if (r.hi == 0.0) {
		/*
		 * When the addends cancel to 0, ensure that the result has
		 * the correct sign.
		 */
		fesetround(oround);
		volatile long double vzs = zs; /* XXX gcc CSE bug workaround */
		return xy.hi + vzs + scalbnl(xy.lo, spread);
	}

	if (oround != FE_TONEAREST) {
		/*
		 * There is no need to worry about double rounding in directed
		 * rounding modes.
		 * But underflow may not be raised correctly, example in downward rounding:
		 * fmal(0x1.0000000001p-16000L, 0x1.0000000001p-400L, -0x1p-16440L)
		 */
		long double ret;
#if defined(FE_INEXACT) && defined(FE_UNDERFLOW)
		int e = fetestexcept(FE_INEXACT);
		feclearexcept(FE_INEXACT);
#endif
		fesetround(oround);
		adj = r.lo + xy.lo;
		ret = scalbnl(r.hi + adj, spread);
#if defined(FE_INEXACT) && defined(FE_UNDERFLOW)
		if (ilogbl(ret) < -16382 && fetestexcept(FE_INEXACT))
			feraiseexcept(FE_UNDERFLOW);
		else if (e)
			feraiseexcept(FE_INEXACT);
#endif
		return ret;
	}

	adj = add_adjusted(r.lo, xy.lo);
	if (spread + ilogbl(r.hi) > -16383)
		return scalbnl(r.hi + adj, spread);
	else
		return add_and_denormalize(r.hi, adj, spread);
}
示例#10
0
static int
print_float (struct printf_info *pinfo, char *startp, char *endp, int *signp, snv_long_double n)
{
  int prec, fmtch;
  char *p, *t;
  snv_long_double fract;
  int expcnt, gformat = 0;
  snv_long_double integer, tmp;
  char expbuf[10];

  prec = pinfo->prec;
  fmtch = pinfo->spec;
  t = startp;
  *signp = 0;

  /* Do the special cases: nans, infinities, zero, and negative numbers. */
  if (isnanl (n))
    {
      /* Not-a-numbers are printed as a simple string. */
      *t++ = fmtch < 'a' ? 'N' : 'n';
      *t++ = fmtch < 'a' ? 'A' : 'a';
      *t++ = fmtch < 'a' ? 'N' : 'n';
      return t - startp;
    }

  /* Zero and infinity also can have a sign in front of them. */
  if (copysignl (1.0, n) < 0.0)
    {
      n = -1.0 * n;
      *signp = '-';
    }

  if (isinfl (n))
    {
      /* Infinities are printed as a simple string. */
      *t++ = fmtch < 'a' ? 'I' : 'i';
      *t++ = fmtch < 'a' ? 'N' : 'n';
      *t++ = fmtch < 'a' ? 'F' : 'f';
      goto set_signp;
    }

  expcnt = 0;
  fract = modfl (n, &integer);

  /* get an extra slot for rounding. */
  *t++ = '0';

  /* get integer portion of number; put into the end of the buffer; the
     .01 is added for modfl (356.0 / 10, &integer) returning .59999999...  */
  for (p = endp - 1; p >= startp && integer; ++expcnt)
    {
      tmp = modfl (integer / 10, &integer);
      *p-- = '0' + ((int) ((tmp + .01L) * 10));
    }

  switch (fmtch)
    {
    case 'g':
    case 'G':
      gformat = 1;

      /* a precision of 0 is treated as a precision of 1. */
      if (!prec)
	pinfo->prec = ++prec;

      /* ``The style used depends on the value converted; style e
         will be used only if the exponent resulting from the
         conversion is less than -4 or greater than the precision.''
                -- ANSI X3J11 */
      if (expcnt > prec || (!expcnt && fract && fract < .0001L))
	{
	  /* g/G format counts "significant digits, not digits of
	     precision; for the e/E format, this just causes an
	     off-by-one problem, i.e. g/G considers the digit
	     before the decimal point significant and e/E doesn't
	     count it as precision.  */
	  --prec;
	  fmtch -= 2;		/* G->E, g->e */
	  goto eformat;
	}
      else
	{
          /* Decrement precision */
          if (n != 0.0L)
	    prec -= (endp - p) - 1;
	  else
	    prec--;

	  goto fformat;
	}

    case 'f':
    case 'F':
    fformat:
      /* reverse integer into beginning of buffer */
      if (expcnt)
	for (; ++p < endp; *t++ = *p);
      else
	*t++ = '0';

      /* If precision required or alternate flag set, add in a
         decimal point.  */
      if (pinfo->prec || pinfo->alt)
	*t++ = '.';

      /* if requires more precision and some fraction left */
      if (fract)
	{
	  if (prec)
	    {
	      /* For %g, if no integer part, don't count initial
	         zeros as significant digits. */
	      do
		{
		  fract = modfl (fract * 10, &tmp);
		  *t++ = '0' + ((int) tmp);
		}
	      while (!tmp && !expcnt && gformat);

	      while (--prec && fract)
		{
		  fract = modfl (fract * 10, &tmp);
		  *t++ = '0' + ((int) tmp);
		}
	    }

	  if (fract)
	    startp =
	      print_float_round (fract, (int *) NULL, startp, t - 1, (char) 0, signp);
	}

      break;

    case 'e':
    case 'E':
    eformat:
      if (expcnt)
	{
	  *t++ = *++p;
	  if (pinfo->prec || pinfo->alt)
	    *t++ = '.';

	  /* if requires more precision and some integer left */
	  for (; prec && ++p < endp; --prec)
	    *t++ = *p;

	  /* if done precision and more of the integer component,
	     round using it; adjust fract so we don't re-round
	     later.  */
	  if (!prec && ++p < endp)
	    {
	      fract = 0;
	      startp = print_float_round ((snv_long_double) 0, &expcnt, startp, t - 1, *p, signp);
	    }

	  /* adjust expcnt for digit in front of decimal */
	  --expcnt;
	}

      /* until first fractional digit, decrement exponent */
      else if (fract)
	{
	  /* adjust expcnt for digit in front of decimal */
	  for (expcnt = -1;; --expcnt)
	    {
	      fract = modfl (fract * 10, &tmp);
	      if (tmp)
		break;
	    }
	  *t++ = '0' + ((int) tmp);
	  if (pinfo->prec || pinfo->alt)
	    *t++ = '.';
	}

      else
	{
	  *t++ = '0';
	  if (pinfo->prec || pinfo->alt)
	    *t++ = '.';
	}

      /* if requires more precision and some fraction left */
      if (fract)
	{
	  if (prec)
	    do
	      {
		fract = modfl (fract * 10, &tmp);
		*t++ = '0' + ((int) tmp);
	      }
	    while (--prec && fract);

	  if (fract)
	    startp = print_float_round (fract, &expcnt, startp, t - 1, (char) 0, signp);
	}
      break;

    default:
      abort ();
    }

  /* %e/%f/%#g add 0's for precision, others trim 0's */
  if (gformat && !pinfo->alt)
    {
      while (t > startp && *--t == '0');
      if (*t != '.')
        ++t;
    }
  else
    for (; prec--; *t++ = '0');

  if (fmtch == 'e' || fmtch == 'E')
    {
      *t++ = fmtch;
      if (expcnt < 0)
        {
          expcnt = -expcnt;
          *t++ = '-';
        }
      else
        *t++ = '+';

      p = expbuf;
      do
        *p++ = '0' + (expcnt % 10);
      while ((expcnt /= 10) > 9);
      *p++ = '0' + expcnt;
      while (p > expbuf)
	*t++ = *--p;
    }

set_signp:
  if (!*signp)
    {
      if (pinfo->showsign)
        *signp = '+';
      else if (pinfo->space)
        *signp = ' ';
    }

  return (t - startp);
}