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 */