Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 04 Mar 1999 20:02:59 +1000
From:      Greg Black <gjb@comkey.com.au>
To:        cjclark@home.com
Cc:        freebsd-questions@FreeBSD.ORG
Subject:   Re: FP Math 
Message-ID:  <19990304100259.6469.qmail@alpha.comkey.com.au>
In-Reply-To: <199903031856.NAA05394@cc942873-a.ewndsr1.nj.home.com>  of Wed, 03 Mar 1999 13:56:30 EST
References:  <199903031856.NAA05394@cc942873-a.ewndsr1.nj.home.com> 

next in thread | previous in thread | raw e-mail | index | archive | help
Well, I've tried to take this off-list, but with no success.
Since nobody has actually flamed me yet for responding, I'll
risk it one more time.

> > There was *no* sarcasm in what I wrote above, just facts --
> > albeit unpalatable facts.
> 
> So, when I rolled my eyes at those who claim that C is a "dangerous"
> language, I was wrong. A single typo in a constant expression will
> erase my home diretory.

I know this whole paragraph was intentionally over the top, but
I think it's important to note that you have claimed two things
here that I did not say.  I did not say that a typo "will" erase
your "home" directory -- I said that a compiler is allowed to
generate anything it likes in response to undefined input; and
my example erased the root directory, not just your home dir :-)

Obviously, nobody would even contemplate using a C compiler
which was likely to generate such code.  However, we all use C
compilers which generate unpredictable code when we give them
undefined input.  If you want consistent results across
platforms, you first need to write code that is defined by the C
language.  This is hardly an imposition.

> > I suggested the Standard for a very good reason.  It's the right
> > place to get answers to this kind of question.  However, a few
> > seconds with K&R2 will find the same thing I've been saying (in
> > Section A6.4) if you don't want to read the Standard.
> 
> Ah, good. Now I understand why you had such objections to my silly
> test programs. I was under the impression that converting from a
> floating point type with higher overflow to one with lower was
> defined. I was confused by the fact that the analogous operation is
> defined for integer types.

I don't know why you refuse to read the references you have
available.  I suggested the Standard, but you don't want to use
it.  You said you had K&R but that it didn't cover this stuff.
I gave you a reference to K&R that does cover it.  Now you make
up new stuff that you'd find is wrong if you looked at K&R.

Surprise, surprise!  The very pragraph before the one I quoted
from K&R for floating conversions discusses integer to float
conversions and it makes clear (as does the Standard) that
conversion of a floating type to an integral type is undefined
if the value (after discarding the fractional part) cannot be
represented in the integral type.

You have a lot of "facts" in your head that are simply not facts
in the real world.  This is a common problem when people with
limited C knowledge start playing with certain parts of the
language, in particular floating point operations.  The answer
is to take time to read carefully from reliable sources and to
try to understand the actual language, without letting one's
preconceptions get in the way of the facts.

> > As for the hope that you can really coerce something with a
> > cast, you can't (but I'm not going to get into the full saga of
> > why that is here).  And, as a general rule, your cast above in:
> > 
> > >   b = (float)a;
> > 
> > is utterly pointless, since it describes the operation that is
> > going to happen anyway.  Even Brian Kernighan and Dennis Ritchie
> > have been known to put in a cast where they shouldn't have, so
> > it's easy to get this wrong.  A good rule, however, is: "don't
> > use casts".  (It's like that other good rule about not using
> > gotos, which has to be broken sometimes too.)
> 
> Do you mean do not use casts in arithmetic operations?

There is a phrase "usual arithmetic conversions" which is to be
found in the indexes of both K&R and the Standard which
describes exactly what happens for these things.  In general,
casts only mask errors here.  If you cast something, you're
telling the compiler you know what you're doing and it will
believe you.  If you leave out the cast, the compiler will tell
you when you have it wrong.  If you're doing maths, then the
compiler will be right.  If you're fiddling with bits for some
clever purpose that you actually understand, then you may need a
cast.  For all the stuff you've shown, casts are a mistake.

> If you don't
> use casts at all, you must get lots of grief from compilers when you
> have all of those null pointers from memory allocations being assigned
> to typed pointers. 

I've read this three times and cannot parse it.  Can you give me
a one line example of what you mean?  (I don't use casts when
they are not required and I never get any grief from compilers.)

If, by chance, you mean that it's necessary to use a cast like
the one at the bottom of p.142 of K&R2 then you're wrong because
that cast is a mistake, as Dennis Ritchie has confirmed when I
challenged him on that.

> I have fixed the bug in the test program. No casting goes on in the RL
> programs that cause troublesome FPEs. I am still trying to get a
> handle on how the FP works and where the problems are. It's been
> getting more interesting. I have tossed aside the attempts to create
> overflows by casting, since, a pointed out, they are undefined
> operations. The program below (finally, I think) has no such issues
> yet creates a SIGFPE core dump,

[Code snipped to show only the parts of interest.]

> int main()
> {
>   double a = 1e200;
>   double b;
> 
>   b = a*a;

All bets are off right here.  The largest double, according to
<float.h> is a little under 1.8e308 -- but you have set b to
1e400 which is outside its range, and that means that the bit
pattern stored at b doesn't have to be a valid floating point
number -- of course, in any reasonable implementation, it should
be +infinity.

[Rest of code snipped.]

> Which returns, 
> 
> fpgetmask: 15
> a:         1.000000e+200
> isinf:     0
> isnan:     0
> Floating exception (core dumped)

That's not what I see.  Look at this:

$ uname -srm
FreeBSD 2.2.8-RELEASE i386
$ ./fptest
fpgetmask: 15
a:         1.000000e+200
isinf:     1
isnan:     0
b:         Inf

This looks like what you're expecting.  The question you now
have to asnwer is why you have set up your system to behave
differently from the default (at least in 2.2.8-R).  I don't
have the beginning of a clue about that, since I barely know
which side of freeBSD is up.

> I went back and checked and the previous programs do the same thing,
> they have been core dumping in the fprintf(). So I tracked the problem
> to vfprintf.c which dies at the line with the arrow (->),

I'm not going to discuss the internals of something like printf
here.  I think it's beyond the possible interest of the list
(and probably outside the ability of most people to understand).

-- 
Greg Black <gjb@acm.org>



To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-questions" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?19990304100259.6469.qmail>