From: apm@kikka.hut.fi (Antti Miettinen)
Subject: gcc-2.3.3, libg++-2.3, IRIX 4.0.1, cout << 123.456
Organization: GNUs Not Usenet
Distribution: gnu
Date: Tue, 5 Jan 1993 05:41:46 GMT

I encountered the following problem while compiling libg++-2.3 with
gcc-2.3.3 on an Indigo with IRIX 4.0.1. It may be a problem in libg++
but it may also be something in gcc as libg++ behaves differently when
it is compiled with different optimization level.

I configured gcc and libg++ with mips-sgi-irix4 and used flags -g -O2
for all compilations. Installation gave no errors but `make check' of
libg++ found a difference in tFile results. It seems that floats and
doubles are output incorrectly with certain values.

Here's the piece of make output:

>./tFile < ./tFile.inp > tFile.out 2>&1
>diff -c tFile.out ./tFile.exp
>*** tFile.out	Sun Jan  3 05:22:36 1993
>--- ./tFile.exp	Tue Nov  3 08:31:35 1992
>***************
>*** 4,11 ****
>  enter three integers (short, int, long):first  = 123 via dec =      123
>  second = 4567 via form = 4567 = 010727 via cout.form = 4567 = 0x11d7
>  third  = 89012 via hex = 15bb4
>! enter a float then a double:first  = <3.456
>! second = -0.00<
>  enter 5 characters separated with spaces:first  = 1
>  rest   =  2 3 4 5
>  
>--- 4,11 ----
>  enter three integers (short, int, long):first  = 123 via dec =      123
>  second = 4567 via form = 4567 = 010727 via cout.form = 4567 = 0x11d7
>  third  = 89012 via hex = 15bb4
>! enter a float then a double:first  = 123.456
>! second = -0.012
>  enter 5 characters separated with spaces:first  = 1
>  rest   =  2 3 4 5

I built libg++ with -g -O1 and after that tFile passed (but make check
failed in tformat) so this may be a bug in gcc. The problem seems to
be function dtoa() in file `floatconv.C'. When it is compiled with -O2
it gives funny results. The following is at least a bit stripped down
(-E plus some editing) test program:

----------------------------------------------------------------
#include <malloc.h>

struct Bigint {
  struct Bigint *next;
  int k, maxwds, sign, wds;
  unsigned long x[1];
};

typedef struct Bigint Bigint;

static Bigint *freelist[15 +1];

static Bigint *
Balloc (int k)
{
  int x;
  Bigint *rv;

  if (rv = freelist[k]) {
    freelist[k] = rv->next;
  }
  else {
    x = 1 << k;
    rv = (Bigint *)malloc(sizeof(Bigint) + (x-1)*sizeof(long));
    rv->k = k;
    rv->maxwds = x;
  }
  rv->sign = rv->wds = 0;
  return rv;
}

static void
Bfree (Bigint *v)
{
  if (v) {
    v->next = freelist[v->k];
    freelist[v->k] = v;
  }
}

static int HIWORD = -1, LOWORD;

static void test_endianness()
{
    union doubleword {
	double d;
	unsigned long u[2];
    } dw;
    dw.d = 10;
    if (dw.u[0] != 0)  
	HIWORD=0, LOWORD=1;
    else
	HIWORD=1, LOWORD=0;
}

static int
hi0bits (register unsigned long x)
{
  register int k = 0;

  if (!(x & 0xffff0000)) {
    k = 16;
    x <<= 16;
  }
  if (!(x & 0xff000000)) {
    k += 8;
    x <<= 8;
  }
  if (!(x & 0xf0000000)) {
    k += 4;
    x <<= 4;
  }
  if (!(x & 0xc0000000)) {
    k += 2;
    x <<= 2;
  }
  if (!(x & 0x80000000)) {
    k++;
    if (!(x & 0x40000000))
      return 32;
  }
  return k;
}

static int
lo0bits (unsigned long *y)
{
  register int k;
  register unsigned long x = *y;

  if (x & 7) {
    if (x & 1)
      return 0;
    if (x & 2) {
      *y = x >> 1;
      return 1;
    }
    *y = x >> 2;
    return 2;
  }
  k = 0;
  if (!(x & 0xffff)) {
    k = 16;
    x >>= 16;
  }
  if (!(x & 0xff)) {
    k += 8;
    x >>= 8;
  }
  if (!(x & 0xf)) {
    k += 4;
    x >>= 4;
  }
  if (!(x & 0x3)) {
    k += 2;
    x >>= 2;
  }
  if (!(x & 1)) {
    k++;
    x >>= 1;
    if (!x & 1)
      return 32;
  }
  *y = x;
  return k;
}

static Bigint *
d2b (double d, int *e, int *bits)
{
  Bigint *b;
  int de, i, k;
  unsigned long *x, y, z;

  b = Balloc(1);

  x = b->x;

  z = ((unsigned long *)&d)[HIWORD]   &  0xfffff ;
  ((unsigned long *)&d)[HIWORD]   &= 0x7fffffff;        

  if (de = (int)(((unsigned long *)&d)[HIWORD]   >>  20 ))
    z |=    0x100000 ;

  if (y = ((unsigned long *)&d)[LOWORD]  ) {
    if (k = lo0bits(&y)) {
      x[0] = y | z << 32 - k;
      z >>= k;
    }
    else
      x[0] = y;
    i = b->wds = (x[1] = z) ? 2 : 1;
  }
  else {
    k = lo0bits(&z);
    x[0] = z;
    i = b->wds = 1;
    k += 32;
  }

  if (de) {
    *e = de - 1023  - (53 -1) + k;
    *bits = 53  - k;
  }
  else {
    *e = de - 1023  - (53 -1) + 1 + k;
    *bits = 32*i - hi0bits(x[i-1]);
  }

  return b;
}

static Bigint *
multadd (Bigint *b, int m, int a)        
{
  int i, wds;
  unsigned long *x, y;
  
  unsigned long xi, z;
  
  Bigint *b1;
  
  wds = b->wds;
  x = b->x;
  i = 0;
  do {
    xi = *x;
    y = (xi & 0xffff) * m + a;
    z = (xi >> 16) * m + (y >> 16);
    a = (int)(z >> 16);
    *x++ = (z << 16) + (y & 0xffff);
  }
  while(++i < wds);
  if (a) {
    if (wds >= b->maxwds) {
      b1 = Balloc(b->k+1);
      memcpy((char *)&b1->sign, (char *)& b->sign,
	     b->wds*sizeof(long) + 2*sizeof(int)) ;
      Bfree(b);
      b = b1;
    }
    b->x[wds++] = a;
    b->wds = wds;
  }
  return b;
}

static Bigint *
mult (Bigint *a, Bigint *b)
{
  Bigint *c;
  int k, wa, wb, wc;
  unsigned long carry, y, z;
  unsigned long *x, *xa, *xae, *xb, *xbe, *xc, *xc0;

  unsigned long z2;

  if (a->wds < b->wds) {
    c = a;
    a = b;
    b = c;
  }
  k = a->k;
  wa = a->wds;
  wb = b->wds;
  wc = wa + wb;
  if (wc > a->maxwds)
    k++;
  c = Balloc(k);
  for(x = c->x, xa = x + wc; x < xa; x++)
    *x = 0;
  xa = a->x;
  xae = xa + wa;
  xb = b->x;
  xbe = xb + wb;
  xc0 = c->x;

  for(; xb < xbe; xb++, xc0++) {
    if (y = *xb & 0xffff) {
      x = xa;
      xc = xc0;
      carry = 0;
      do {
	z = (*x & 0xffff) * y + (*xc & 0xffff) + carry;
	carry = z >> 16;
	z2 = (*x++ >> 16) * y + (*xc >> 16) + carry;
	carry = z2 >> 16;
	(*xc++ =  z2 << 16 |  z & 0xffff) ;
      }
      while(x < xae);
      *xc = carry;
    }
    if (y = *xb >> 16) {
      x = xa;
      xc = xc0;
      carry = 0;
      z2 = *xc;
      do {
	z = (*x & 0xffff) * y + (*xc >> 16) + carry;
	carry = z >> 16;
	(*xc++ =  z << 16 |  z2 & 0xffff) ;
	z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry;
	carry = z2 >> 16;
      }
      while(x < xae);
      *xc = z2;
    }
  }

  for(xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ;
  c->wds = wc;
  return c;
}

static Bigint *p5s;

static Bigint *
i2b (int i)
{
  Bigint *b;

  b = Balloc(1);
  b->x[0] = i;
  b->wds = 1;
  return b;
}

static Bigint *
pow5mult (Bigint *b, int k)
{
  Bigint *b1, *p5, *p51;
  int i;
  static int p05[3] = { 5, 25, 125 };
  
  if (i = k & 3)
    b = multadd(b, p05[i-1], 0);
  
  if (!(k >>= 2))
    return b;
  if (!(p5 = p5s)) {
    p5 = p5s = i2b(625);
    p5->next = 0;
  }
  for(;;) {
    if (k & 1) {
      b1 = mult(b, p5);
      Bfree(b);
      b = b1;
    }
    if (!(k >>= 1))
      break;
    if (!(p51 = p5->next)) {
      p51 = p5->next = mult(p5,p5);
      p51->next = 0;
    }
    p5 = p51;
  }
  return b;
}

static Bigint *
lshift (Bigint *b, int k)
{
  int i, k1, n, n1;
  Bigint *b1;
  unsigned long *x, *x1, *xe, z;

  n = k >> 5;
  k1 = b->k;
  n1 = n + b->wds + 1;
  for(i = b->maxwds; n1 > i; i <<= 1)
    k1++;
  b1 = Balloc(k1);
  x1 = b1->x;
  for(i = 0; i < n; i++)
    *x1++ = 0;
  x = b->x;
  xe = x + b->wds;

  if (k &= 0x1f) {
    k1 = 32 - k;
    z = 0;
    do {
      *x1++ = *x << k | z;
      z = *x++ >> k1;
    }
    while(x < xe);
    if (*x1 = z)
      ++n1;
  }
  else do
    *x1++ = *x++;
  while(x < xe);
  b1->wds = n1 - 1;
  Bfree(b);
  return b1;
}

static int
cmp (Bigint *a, Bigint *b)
{
  unsigned long *xa, *xa0, *xb, *xb0;
  int i, j;
  
  i = a->wds;
  j = b->wds;
  
  if (i -= j)
    return i;
  xa0 = a->x;
  xa = xa0 + j;
  xb0 = b->x;
  xb = xb0 + j;
  for(;;) {
    if (*--xa != *--xb)
      return *xa < *xb ? -1 : 1;
    if (xa <= xa0)
      break;
  }
  return 0;
}

static int quorem (Bigint *b, Bigint *S)
{
  int n;
  long borrow, y;
  unsigned long carry, q, ys;
  unsigned long *bx, *bxe, *sx, *sxe;
  
  long z;
  unsigned long si, zs;
   
  n = S->wds;

  if (b->wds < n)
    return 0;
  sx = S->x;
  sxe = sx + --n;
  bx = b->x;
  bxe = bx + n;
  q = *bxe / (*sxe + 1);   
  
  if (q) {
    borrow = 0;
    carry = 0;
    do {
      si = *sx++;
      ys = (si & 0xffff) * q + carry;
      zs = (si >> 16) * q + (ys >> 16);
      carry = zs >> 16;
      y = (*bx & 0xffff) - (ys & 0xffff) + borrow;
      borrow = y >> 16;
      ;
      z = (*bx >> 16) - (zs & 0xffff) + borrow;
      borrow = z >> 16;
      ;
      (*bx++ =  z << 16 |  y & 0xffff) ;
    }
    while(sx <= sxe);
    if (!*bxe) {
      bx = b->x;
      while(--bxe > bx && !*bxe)
	--n;
      b->wds = n;
    }
  }
  if (cmp(b, S) >= 0) {
    q++;
    borrow = 0;
    carry = 0;
    bx = b->x;
    sx = S->x;
    do {
      si = *sx++;
      ys = (si & 0xffff) + carry;
      zs = (si >> 16) + (ys >> 16);
      carry = zs >> 16;
      y = (*bx & 0xffff) - (ys & 0xffff) + borrow;
      borrow = y >> 16;
      ;
      z = (*bx >> 16) - (zs & 0xffff) + borrow;
      borrow = z >> 16;
      ;
      (*bx++ =  z << 16 |  y & 0xffff) ;
    }
    while(sx <= sxe);
    bx = b->x;
    bxe = bx + n;
    if (!*bxe) {
      while(--bxe > bx && !*bxe)
	--n;
      b->wds = n;
    }
  }
  return q;
}

static Bigint *
diff (Bigint *a, Bigint *b)
{
  Bigint *c;
  int i, wa, wb;
  long borrow, y;  
  unsigned long *xa, *xae, *xb, *xbe, *xc;
  
  long z;
  
  i = cmp(a,b);
  if (!i) {
    c = Balloc(0);
    c->wds = 1;
    c->x[0] = 0;
    return c;
  }
  if (i < 0) {
    c = a;
    a = b;
    b = c;
    i = 1;
  }
  else
    i = 0;
  c = Balloc(a->k);
  c->sign = i;
  wa = a->wds;
  xa = a->x;
  xae = xa + wa;
  wb = b->wds;
  xb = b->x;
  xbe = xb + wb;
  xc = c->x;
  borrow = 0;
  
  do {
    y = (*xa & 0xffff) - (*xb & 0xffff) + borrow;
    borrow = y >> 16;
    ;
    z = (*xa++ >> 16) - (*xb++ >> 16) + borrow;
    borrow = z >> 16;
    ;
    (*xc++ =  z << 16 |  y & 0xffff) ;
  }
  while(xb < xbe);
  while(xa < xae) {
    y = (*xa & 0xffff) + borrow;
    borrow = y >> 16;
    ;
    z = (*xa++ >> 16) + borrow;
    borrow = z >> 16;
    ;
    (*xc++ =  z << 16 |  y & 0xffff) ;
  }
  
  while(!*--xc)
    wa--;
  c->wds = wa;
  return c;
}

static double tens[] = {
  1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
  1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
  1e20, 1e21, 1e22,
};

static double bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 };

static char *
dtoa (double d, int mode, int ndigits, int *decpt, int *sign, char **rve)
{
  int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1;
  int j, j1, k, k0, k_check, leftright, m2, m5, s2, s5;
  int spec_case, try_quick;
  long L;
  
  int denorm;
  unsigned long x;
  
  Bigint *b, *b1, *delta, *mlo, *mhi, *S;
  double d2, ds, eps;
  char *s, *s0;
  static Bigint *result;
  static int result_k;
  
  if (HIWORD<0) test_endianness(); ;
  if (result) {
    result->k = result_k;
    result->maxwds = 1 << result_k;
    Bfree(result);
    result = 0;
  }
  
  if (((unsigned long *)&d)[HIWORD]  & 0x80000000 ) {
    *sign = 1;
    ((unsigned long *)&d)[HIWORD]  &= ~0x80000000 ;   
  }
  else
    *sign = 0;
  
  if ((((unsigned long *)&d)[HIWORD]  &  0x7ff00000 ) ==  0x7ff00000 )    
    {
      *decpt = 9999;
      s = !((unsigned long *)&d)[LOWORD]  && !(((unsigned long *)&d)[HIWORD]
					       & 0xfffff) ? "Infinity" : "NaN";
      if (rve)
	*rve = s[3] ? s + 8 :
      s + 3;
      return s;
    }
  
  if (!d) {
    *decpt = 1;
    s = "0";
    if (rve)
      *rve = s + 1;
    return s;
  }
  
  b = d2b(d, &be, &bbits);

  if (i = (int)(((unsigned long *)&d)[HIWORD]  >> 20  & ( 0x7ff00000 >>20 ))) {
    d2 = d;
    ((unsigned long *)&d2)[HIWORD]  &= 0xfffff ;
    ((unsigned long *)&d2)[HIWORD]  |= 0x3ff00000 ;
    i -= 1023 ;
    denorm = 0;
  }
  else {
    i = bbits + be + (1023  + (53 -1) - 1);
    x = i > 32  ? ((unsigned long *)&d)[HIWORD]  << 64 - i
      | ((unsigned long *)&d)[LOWORD]  >> i - 32
      : ((unsigned long *)&d)[LOWORD]  << 32 - i;
    d2 = x;
    ((unsigned long *)&d2)[HIWORD]  -= 31*   0x100000 ;  
    i -= (1023  + (53 -1) - 1) + 1;
    denorm = 1;
  }
  
  ds = (d2-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981;
  k = (int)ds;
  if (ds < 0. && ds != k)
    k--;     
  k_check = 1;
  if (k >= 0 && k <= 22 ) {
    if (d < tens[k])
      k--;
    k_check = 0;
  }
  j = bbits - i - 1;
  if (j >= 0) {
    b2 = 0;
    s2 = j;
  }
  else {
    b2 = -j;
    s2 = 0;
  }
  if (k >= 0) {
    b5 = 0;
    s5 = k;
    s2 += k;
  }
  else {
    b2 -= k;
    b5 = -k;
    s5 = 0;
  }
  if (mode < 0 || mode > 9)
    mode = 0;
  try_quick = 1;
  if (mode > 5) {
    mode -= 4;
    try_quick = 0;
  }
  leftright = 1;
  switch(mode) {
  case 0:
  case 1:
    ilim = ilim1 = -1;
    i = 18;
    ndigits = 0;
    break;
  case 2:
    leftright = 0;
  case 4:
    if (ndigits <= 0)
      ndigits = 1;
    ilim = ilim1 = i = ndigits;
    break;
  case 3:
    leftright = 0;
  case 5:
    i = ndigits + k + 1;
    ilim = i;
    ilim1 = i - 1;
    if (i <= 0)
      i = 1;
  }
  j = sizeof(unsigned long);
  for(result_k = 0; sizeof(Bigint) - sizeof(unsigned long) + j < i;
      j <<= 1) result_k++;
  result = Balloc(result_k);
  s = s0 = (char *)result;
  
  if (ilim >= 0 && ilim <= 14  && try_quick) {
    i = 0;
    d2 = d;
    k0 = k;
    ilim0 = ilim;
    ieps = 2;  
    if (k > 0) {
      ds = tens[k&0xf];
      j = k >> 4;
      if (j & 0x10 ) {
	j &= 0x10  - 1;
	d /= bigtens[5 -1];
	ieps++;
      }
      for(; j; j >>= 1, i++)
	if (j & 1) {
	  ieps++;
	  ds *= bigtens[i];
	}
      d /= ds;
    }
    else if (j1 = -k) {
      d *= tens[j1 & 0xf];
      for(j = j1 >> 4; j; j >>= 1, i++)
	if (j & 1) {
	  ieps++;
	  d *= bigtens[i];
	}
    }
    if (k_check && d < 1. && ilim > 0) {
      if (ilim1 <= 0)
	goto fast_failed;
      ilim = ilim1;
      k--;
      d *= 10.;
      ieps++;
    }
    eps = ieps*d + 7.;
    ((unsigned long *)&eps)[HIWORD]  -= (53 -1)*   0x100000 ;
    if (ilim == 0) {
      S = mhi = 0;
      d -= 5.;
      if (d > eps)
	goto one_digit;
      if (d < -eps)
	goto no_digits;
      goto fast_failed;
    }
    
    if (leftright) {
      eps = 0.5/tens[ilim-1] - eps;
      for(i = 0;;) {
	L = (long)d;
	d -= L;
	*s++ = '0' + (int)L;
	if (d < eps)
	  goto ret1;
	if (1. - d < eps)
	  goto bump_up;
	if (++i >= ilim)
	  break;
	eps *= 10.;
	d *= 10.;
      }
    }
    else {
      eps *= tens[ilim-1];
      for(i = 1;; i++, d *= 10.) {
	L = (long)d;
	d -= L;
	*s++ = '0' + (int)L;
	if (i == ilim) {
	  if (d > 0.5 + eps)
	    goto bump_up;
	  else if (d < 0.5 - eps) {
	    while(*--s == '0');
	    s++;
	    goto ret1;
	  }
	  break;
	}
      }
      
    }
    
  fast_failed:
    s = s0;
    d = d2;
    k = k0;
    ilim = ilim0;
  }
  
  if (be >= 0 && k <= 14 ) {
    
    ds = tens[k];
    if (ndigits < 0 && ilim <= 0) {
      S = mhi = 0;
      if (ilim < 0 || d <= 5*ds)
	goto no_digits;
      goto one_digit;
    }
    for(i = 1;; i++) {
      L = (long)(d / ds);
      d -= L*ds;
      
      *s++ = '0' + (int)L;
      if (i == ilim) {
	d += d;
	if (d > ds || d == ds && L & 1) {
	bump_up:
	  while(*--s == '9')
	    if (s == s0) {
	      k++;
	      *s = '0';
	      break;
	    }
	  ++*s++;
	}
	break;
      }
      if (!(d *= 10.))
	break;
    }
    goto ret1;
  }
  
  m2 = b2;
  m5 = b5;
  mhi = mlo = 0;
  if (leftright) {
    if (mode < 2) {
      i = denorm ? be + (1023  + (53 -1) - 1 + 1) :
      1 + 53  - bbits;
    }
    else {
      j = ilim - 1;
      if (m5 >= j)
	m5 -= j;
      else {
	s5 += j -= m5;
	b5 += j;
	m5 = 0;
      }
      if ((i = ilim) < 0) {
	m2 -= i;
	i = 0;
      }
    }
    b2 += i;
    s2 += i;
    mhi = i2b(1);
  }
  if (m2 > 0 && s2 > 0) {
    i = m2 < s2 ? m2 : s2;
    b2 -= i;
    m2 -= i;
    s2 -= i;
  }
  if (b5 > 0) {
    if (leftright) {
      if (m5 > 0) {
	mhi = pow5mult(mhi, m5);
	b1 = mult(mhi, b);
	Bfree(b);
	b = b1;
      }
      if (j = b5 - m5)
	b = pow5mult(b, j);
    }
    else
      b = pow5mult(b, b5);
  }
  S = i2b(1);
  if (s5 > 0)
    S = pow5mult(S, s5);
  
  if (mode < 2) {
    if (!((unsigned long *)&d)[LOWORD]
	&& !(((unsigned long *)&d)[HIWORD]  &  0xfffff )
	&& ((unsigned long *)&d)[HIWORD]  &  0x7ff00000 ) {
      b2 += 1 ;
      s2 += 1 ;
      spec_case = 1;
    }
    else
      spec_case = 0;
  }
  
  if (i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f)
    i = 32 - i;

  if (i > 4) {
    i -= 4;
    b2 += i;
    m2 += i;
    s2 += i;
  }
  else if (i < 4) {
    i += 28;
    b2 += i;
    m2 += i;
    s2 += i;
  }
  if (b2 > 0)
    b = lshift(b, b2);
  if (s2 > 0)
    S = lshift(S, s2);
  if (k_check) {
    if (cmp(b,S) < 0) {
      k--;
      b = multadd(b, 10, 0);   
      if (leftright)
	mhi = multadd(mhi, 10, 0);
      ilim = ilim1;
    }
  }
  if (ilim <= 0 && mode > 2) {
    if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) {
      
    no_digits:
      k = -1 - ndigits;
      goto ret;
    }
  one_digit:
    *s++ = '1';
    k++;
    goto ret;
  }
  if (leftright) {
    if (m2 > 0)
      mhi = lshift(mhi, m2);
    
    mlo = mhi;
    if (spec_case) {
      mhi = Balloc(mhi->k);
      memcpy((char *)&mhi->sign, (char *)& mlo->sign,
	     mlo->wds*sizeof(long) + 2*sizeof(int)) ;
      mhi = lshift(mhi, 1 );
    }
    
    for(i = 1;;i++) {
      dig = quorem(b,S) + '0';

      j = cmp(b, mlo);
      delta = diff(S, mhi);
      j1 = delta->sign ? 1 : cmp(b, delta);
      Bfree(delta);
      
      if (j1 == 0 && !mode && !(((unsigned long *)&d)[LOWORD]  & 1)) {
	if (dig == '9')
	  goto round_9_up;
	if (j > 0)
	  dig++;
	*s++ = dig;
	goto ret;
      }
      
      if (j < 0 || j == 0 && !mode
	  
	  && !(((unsigned long *)&d)[LOWORD]  & 1)
	  
	  ) {
	if (j1 > 0) {
	  b = lshift(b, 1);
	  j1 = cmp(b, S);
	  if ((j1 > 0 || j1 == 0 && dig & 1)
	      && dig++ == '9')
	    goto round_9_up;
	}
	*s++ = dig;
	goto ret;
      }
      if (j1 > 0) {
	if (dig == '9') {  
	round_9_up:
	  *s++ = '9';
	  goto roundoff;
	}
	*s++ = dig + 1;
	goto ret;
      }
      *s++ = dig;
      if (i == ilim)
	break;
      b = multadd(b, 10, 0);
      if (mlo == mhi)
	mlo = mhi = multadd(mhi, 10, 0);
      else {
	mlo = multadd(mlo, 10, 0);
	mhi = multadd(mhi, 10, 0);
      }
    }
  }
  else
    for(i = 1;; i++) {
      *s++ = dig = quorem(b,S) + '0';
      if (i >= ilim)
	break;
      b = multadd(b, 10, 0);
    }
  
  
  
  b = lshift(b, 1);
  j = cmp(b, S);
  if (j > 0 || j == 0 && dig & 1) {
  roundoff:
    while(*--s == '9')
      if (s == s0) {
	k++;
	*s++ = '1';
	goto ret;
      }
    ++*s++;
  }
  else {
    while(*--s == '0');
    s++;
  }
 ret:
  Bfree(S);
  if (mhi) {
    if (mlo && mlo != mhi)
      Bfree(mlo);
    Bfree(mhi);
  }
 ret1:
  Bfree(b);
  *s = 0;
  *decpt = k + 1;
  if (rve)
    *rve = s;
  return s0;
}

#include <stdio.h>

main()
{
  int decpt, sign;
  char *rve;

  printf ("%s\n", dtoa(123.456, 2, 6, &decpt, &sign, &rve));
}
----------------------------------------------------------------

When compiled with -O2 -fno-schedule-insns it outputs `123456'. When
compiled with -O -fschedule-insns it outputs `<3456'.

With gcc-2.2.2 the program outputs `123456' when compiled with -O2.



Newsgroups: gnu.gcc.bug