Thread View: gnu.gcc.bug
1 messages
1 total messages
Started by Antti Miettinen
Tue, 05 Jan 1993 05:41
gcc-2.3.3, libg++-2.3, IRIX 4.0.1, cout << 123.456
Author: Antti Miettinen
Date: Tue, 05 Jan 1993 05:41
Date: Tue, 05 Jan 1993 05:41
1056 lines
20469 bytes
20469 bytes
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.
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads