I'm having problems thinking of a scenario where this could happen with unary "-". Could you give some example where both preprocessing results are valid, but have different meaning?
This is something that ANSI C (C89) fixed, introducing the idea of ‘preprocessing tokens’ used in some of the conceptual translation phases. The two ‘-’ are separate preprocessing tokens because they did not originally appear together, so they turn into separate C tokens ‘-’ ‘-’ rather than one ‘--’. (If preprocessed code needs to be represented as text again (e.g. output from cc -E) then white space between the two ensures this.)
A pre-ANSI preprocessor would generally emit ‘--’, which the compiler would naturally recognize as a decrement operator. I'm not aware of any exceptions; pre-ANSI implementations diverged in various ways, but tended to follow either K&R 1 or Reiser (John, not Hans) CPP.
That's the reason for ps... But either way - what I meant is that it doesn't run just a text replace, it has to split the tokens first. Otherwise SOME_MONE_TEXT would get turned into SOME_-1_TEXT too. Lexer has to detect where the whole token exists on its own and replace it with equivalent syntax.
It's not a special way of writing two.
It was a way of getting identical bit patterns for IEEE floats on all platforms.
Until recently, most compilers would do host arithmetic and then convert it to target bit pattern. You would get within epsilon equal values, but not always the same bit pattern.
Now all these compilers use multiprecision float libraries (either MPFR or custom-written), so the bit patterns will always come out the same.
As such, there is no need for the explicit bit patterns anymore, so they just use "2.0".
Looking at the diff they're now using the new hexadecimal format for representing IEEE floats, which didn't exist until recently but is a much cleaner way of writing bit-exact float values.
Mostly for testing and the ability to reproduce the same issue/error/bug on many different platforms. Before it could be a little hard to debug if you compiled on one machine that had one interpretation of IEEE754 (most likely in when to round and what direction) for releases and the devs all had a machine that did it another way. This would mean that the values would be different and could throw off quite a few things for simulations and other areas with heavy floating point numbers.
That same compiler need not produce the same code for each target. For example, one CPU might be so slow running instruction X that it is faster to emulate it, while it could be faster on the other.
"As far as I know, the K5 is the only x86 family CPU that did sin/cos accurately. AMD went back to being bit-for-bit compatibile with the old x87 behavior, assumably because too many applications broke"
What I meant is if your primary concert is identical results it should be using the same target, with no runtime changing based on instructions on one processor or another.
Anyway, K5 was almost two decades ago. If you use recent processors, or even better avoid x87 instructions entirely, are you still going to have different float results?
How do you check that your code never switches paths depending on CPU architecture? How do you guarantee that for the (third party) libraries you use, including your C library?
Also, I think modern x86 has a "approximate 1/x" instruction that is there to be as fast as possible and, because of that, allows for differences in results. I don't know whether that is true, or whether different implementations actually exist, though.
In the end though that sounds like you can't be entirely sure that chips in different generations are consistent, so it's not really a manufacturer difference problem.
Those constants are meant to be used in low level floating point library code. So bit patterns are critical here if you don't want these functions broken in a subtle way.