cudcv@daisy.warwick.UUCP (Rob McMahon) (04/03/86)
<munch>
Pointed out to me by someone here - what does your favourite C compiler make
of this program :
main()
{
unsigned long u;
double d;
float f;
u = ~0;
d = u;
f = u;
printf("u = %lu f = %f d = %lf\n", u, f, d);
if (d < 0) printf("d < 0\n");
if (f < 0) printf("f < 0\n");
}
On a VAX-780 running 4.2bsd or a Sun-2 running 2.0 it gives
u = 4294967295 f = -1.000000 d = -1.000000
d < 0
f < 0
On a Gould PN6000 running UTX/32 1.2 it gives
u = 4294967295 f = -1.000000 d = 4294967295.000000
f < 0
-----
UUCP: ...!mcvax!ukc!warwick!cudcv
JANET: cudcv%uk.ac.warwk.daisy
PHONE: +44 204 523037
Rob McMahon, Computer Unit, Warwick University, Coventry CV4 7AL, England
--
UUCP: ...!mcvax!ukc!warwick!cudcv
ARPA: cudcv%warwk.daisy@ucl-cs.ARPA
PHONE: +44 204 523037
Rob McMahon, Computer Unit, Warwick University, Coventry CV4 7AL, England
gwyn@brl-smoke.ARPA (Doug Gwyn ) (04/04/86)
In article <144@daisy.warwick.UUCP> cudcv@daisy.warwk.ac.uk (Rob McMahon) writes: >main() >{ > unsigned long u; > double d; > float f; > > u = ~0; > d = u; > f = u; > printf("u = %lu f = %f d = %lf\n", u, f, d); > if (d < 0) printf("d < 0\n"); > if (f < 0) printf("f < 0\n"); >} > >On a VAX-780 running 4.2bsd or a Sun-2 running 2.0 it gives > >u = 4294967295 f = -1.000000 d = -1.000000 >d < 0 >f < 0 > >On a Gould PN6000 running UTX/32 1.2 it gives > > >u = 4294967295 f = -1.000000 d = 4294967295.000000 >f < 0 The Gould almost got it right; f should also be a large number, approximately the same as d. The SVR2 VAX PCC gets it right.
wendyt@pyramid.UUCP (Wendy Thrash) (04/08/86)
In article <144@daisy.warwick.UUCP> cudcv@daisy.warwk.ac.uk (Rob McMahon) writes >Pointed out to me by someone here - what does your favourite C compiler make >of this program : >[program involving conversion of large unsigned to float/double] A few months ago I posted a similar (but much larger) program to net.lang.c. (My address at that time was ...pyramid!isieng!wendyt, for you greppers.) Several people posted followups, others sent me mail, and I eventually summarized to the net. If you're interested in this problem you might want to check your news archives, but to summarize briefly, Vaxen running System V tend to do things right; just about everyone else messes up something (including the compiler I was working on at the time). This problem arises because hardware usually provides instructions to convert float/double to/from int, but never seems to provide instructions for unsigned conversion. Doing the unsigned conversions correctly is a real pain in the bazooka for a compiler writer, so s/he tends to take an "Oh well, who'd want to do this anyway?" approach. This is, of course, very bad form. But say, folks, when you see something like this on the net and find it to produce bizarre results on your hardware, please send a note off to the manufacturer! Believe it or not, not all hardware makers read the news; perhaps some who don't still read their bug reports.
daemon@houligan.UUCP (04/19/86)
<EAT THIS LINE> I offer the following bits with the understanding that I do not work for UTX support and have no access to the source, so please don't bombard me with bug reports or fixes. >Try this on your favorite C compiler and see what you get. > >main() >{ > unsigned u; > double d; > float f; > > u = ~0; > d = ((float)(u))+1; > f = ((float)(u))+1; > printf("u = %lu f = %f d = %lf\n", u, f, d); > if (d < 0) printf("d < 0\n"); > if (f < 0) printf("f < 0\n"); >} > >On a VAX-780 running 4.2bsd or a Sun-2 running 2.0 it gives > >u = 4294967295 f = -1.000000 d = -1.000000 >d < 0 >f < 0 > >On a Gould PN6000 running UTX/32 1.2 it gives > > >u = 4294967295 f = -1.000000 d = 4294967295.000000 >f < 0 > I tried the given example on our PN9080 and got the same results that the author of the original article got on the 6000. The float value comes out -1, and the double value comes out to the large positive value which is the value of the unsigned. On the other hand, if you do this: main() { unsigned u; double d; float f; u = ~0; d = (float) u; f = (float) u; printf("u = %lu f = %f d = %lf\n", u, f, d); if (d < 0) printf("d < 0\n"); if (f < 0) printf("f < 0\n"); } you get the same results as the VAX. It could be a problem with the Gould compiler, which probably works by converting the unsigned to an 8-byte quantity (there is a machine instruction that will extend the sign of an integer through 8 bytes), then converting the result to an 8-byte floating- point variable. Apparently, in the first example, it fails for some reason to do the sign extension. But, now for a larger question: I claim that both the VAX and Gould results are incorrect. The Kernighan and Ritchie book doesn't say anything about converting unsigned quantities directly to float, but I think that if I wanted to assign an unsigned quantity to a float or double, I would damn well expect to get a positive number. It doesn't make sense to me to take something that is explicitly declared as unsigned and treat it as if it were signed. (However, I fear that most machines don't have a convert- unsigned-to-float instruction, so I may be stuck with this.) What does everyone out there think? Dave Cornutt Gould Computer Systems Ft. Lauderdale, FL gould!dcornutt (if it works) "The opinions expressed herein are not necessarily those of my employer; in fact, the opinions expressed herein are not necessary."