[floats][infinity][C99]
Daniel Kochmański
daniel at turtleware.eu
Fri Sep 4 16:54:46 UTC 2015
Raymond Toy writes:
>>>>>> "Daniel" == Daniel Kochma <Daniel> writes:
>
> Daniel> Thanks for reply.
> Daniel> Raymond Toy writes:
>
> >>>>>>> "Daniel" == Daniel Kochma <Daniel> writes:
> >>
> Daniel> Hello,
> Daniel> I'm little in doubt. Problem is related to ieee-floating-point
> Daniel> extensions, which provide infinities and nan. Everything works fine
> Daniel> until we generate C code, which simply breaks, because it isn't taken
> Daniel> into account.
> >>
> Daniel> There are two possible solutions:
> >>
> Daniel> - for these cases use constant expressions, which trigger an error on
> Daniel> some compilers, that is (0.0 / 0.0) for nan, (1.0 / 0.0) for infinity
> >>
> >>
> Daniel> - use defined by C99 macros: INFINITY and NAN, which will work on any
> Daniel> compiler supporting C99.
> >>
> >> Option 3: Create them yourself in portable C. Something like
> >>
> >> union {
> >> int i[2];
> >> double d;
> >> } u;
> >>
> >> /* +Infinity */
> >> u.i[MSB] = 0x7ff00000;
> >> u.i[LSB] = 0;
> >> u.d is +Infinity
> >>
> >> where MSB and LSB are 0 or 1 depending on the endianness of machine.
> >> If you have 64-bit integers, you can replace int i[2] with long i and
> >> just use i = 0x7ff0000000000000;
> >>
> >> This works for NaN too, but there are many different values for NaN,
> >> so you'll have to choose something.
>
> Daniel> We have at least three float types – short-float, single-float and
> Daniel> double-float, plus on some architectures long-float. Will this approach
> Daniel> work on all of these types?
>
> Is short-float the same as single-float (like in gcl)? If so, I think
> you can use
>
> union {
> int i;
> float f;
> }
Yes, it's the same, but it's implementation detail (however infinity
representation is implementation detail too, so all OK).
>
> If long-float is the x87 double-extended (80-bit) float, you'll have to do a
> bit more work. Perhaps something like
>
> union {
> short s[5];
> long double ld;
> }
>
> Daniel> Also, we'll have to define such infinity for each architecture
> Daniel> separately, depending on the endianess?
>
> Yes, probably. But you only need to set up MSB/LSB to get the right
> thing. I think. At least that's how fdlibm works and how cmucl
> produces it's infinities (in C code). Of course in Lisp, cmucl has
> special builtins to create floats from bits appropriately. Perhaps
> ecl can do something similar. (But there are separate implementations
> for each architecture.)
I'd rather avoid that. ECL runs now on number of architectures I have no
access too.
>
> Daniel> I'm don't know float numbers well enough, but soft floats and hard
> Daniel> floats on arm architecture make any difference for us, or C compiler
> Daniel> will handle it without any intervention?
>
> This is pretty handy:
> http://babbage.cs.qc.edu/courses/cs341/IEEE-754.html
>
> While I know long ago soft-floats didn't always match the format of
> hard floats, I suspect those days are long gone and any soft float
> implementation uses exactly the same format as hard floats.
>
> BTW, pjb pointed out to me (in private) that the union code isn't
> truly portable C. He's right, but for the architectures you're
> running on, it should probably work fine.
As above, I'd rather avoid that. Also - we handle ieee754 floats
correctly in a very portable manner. It's rather question about: "what
should we put in places, where constant value may be used" (compiler
supports locatives, and if binding carries float, then it inserts it's
value without passing float variable). Consider this (it's not actual
output, but more or less it should show a mechanizm):
(let ((a ext:float-positive-infinity))
(setf *x* (< 0.0 3.3))
(setf *y* (< 0.0 a)))
-->
bool x, y;
x = (float)0.0 < (float)3.3;
y = (float)0.0 < INFINITY; /* a is optimized out */
--
Daniel Kochmański | Poznań, Poland
;; aka jackdaniel
"Be the change that you wish to see in the world." - Mahatma Gandhi
More information about the ecl-devel
mailing list