▲ | BlackFly 3 days ago | ||||||||||||||||||||||||||||
You can exploit the exactness of (specific) floating point operations in test data by using sums of powers of 2. Polynomials with such coefficients produce exact results so long as the overall powers are within ~53 powers of 2 (don't quote me exactly on that, I generally don't push the range very high!). You can find exact polynomial solutions to linear PDEs with such powers using high enough order finite difference methods for example. However, the story about non-determinism is no myth. The intel processors have a separate math coprocessor that supports 80bit floats (https://en.wikipedia.org/wiki/Extended_precision#x86_extende...). Moving a float from a register in this coprocessor to memory truncates the float. Repeated math can be done inside this coprocessor to achieve higher precision so hot loops generally don't move floats outside of these registers. Non-determinism occurs in programs running on intel with floats when threads are interrupted and the math coprocessor flushed. The non-determinism isn't intrinsic to the floating point arithmetic but to the non-determinism of when this truncation may occur. This is more relevant for fields where chaotic dynamics occur. So the same program with the same inputs can produce different results. NaN is an error. If you take the square root of a negative number you get a NaN. This is just a type error, use complex numbers to overcome this one. But then you get 0. / 0. and that's a NaN or Inf - Inf and a whole slew of other things that produce out of bounds results. Whether it is expected or not is another story, but it does mean that you are unable to represent the value with a float and that is a type error. | |||||||||||||||||||||||||||||
▲ | AshamedCaptain 3 days ago | parent | next [-] | ||||||||||||||||||||||||||||
> Non-determinism occurs in programs running on intel with floats when threads are interrupted and the math coprocessor flushed That's ridiculous. No OS in his right mind would flush FPU regs to 64 bits only, because that would break many things, most obviously "real" 80 bit FP which is still a thing and the only reason x87 instructions still work. It would even break plain equality comparisons making all FP useless. For 64 bit FP most compilers prefer SSE rather than x87 instructions these days. | |||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||
▲ | nyeah 2 days ago | parent | prev | next [-] | ||||||||||||||||||||||||||||
NaN is not necessarily an error. It might be fine. It depends on what you're doing with it. If NaN is invalid input for the next step, then sure why not treat it as an error? But that's a design decision not an imperative that everybody must follow. (I picture Mel Brooks' 15 commandments, #11-15, that fell and broke. This is not like that.) | |||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||
▲ | jcranmer 3 days ago | parent | prev | next [-] | ||||||||||||||||||||||||||||
Wow, you're crossing a few wires in your zeal to provide information to the point that you're repeating myths. > The intel processors have a separate math coprocessor that supports 80bit floats x86 processors have two FPU units, the x87 unit (that you're describing) and the SSE unit. Anyone compiling for x86-64 uses the SSE unit for default, and most x86-32 compilers still default to SSE anyways. > Moving a float from a register in this coprocessor to memory truncates the float. No it doesn't. The x87 unit has load and store instructions for 32-bit, 64-bit, and 80-bit floats. If you want to spill 80-bit values as 80-bit values, you can do so. > Repeated math can be done inside this coprocessor to achieve higher precision so hot loops generally don't move floats outside of these registers. Hot loops these days use the SSE stuff because they're so much faster than x87. Friends don't let friends use long double without good reason! > Non-determinism occurs in programs running on intel with floats when threads are interrupted and the math coprocessor flushed. Lol, nope. You'll spill the x87 register stack on thread context switch with FSAVE or FXSAVE or XSAVE, all of which will store the registers as 80-bit values without loss of precision. That said, there was a problem with programs that use the x87 unit, but it has absolutely nothing to do with what you're describing. The x87 unit doesn't have arithmetic for 32-bit and 64-bit values, only 80-bit values. Many compilers, though, just pretended that the x87 unit supported arithmetic on 32-bit and 64-bit values, so that FADD would simultaneously be a 32-bit addition, a 64-bit addition, and a 80-bit addition. If the compiler needed to spill a floating-point register, they would spill the value as a 32-bit value (if float) or 64-bit value (if double), and register spills are pretty unpredictable for user code. That's the nondeterminism you're referring to, and it's considered a bug in every compiler I'm aware of. (See https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p37... for a more thorough description of the problem). | |||||||||||||||||||||||||||||
| |||||||||||||||||||||||||||||
▲ | bobmcnamara 3 days ago | parent | prev [-] | ||||||||||||||||||||||||||||
> Non-determinism occurs in programs running on intel FTFY. They even changed some of the more obscure handling between 8087,80287,80387. So much hoop jumping if you cared about binary reproducibility. Seems to be largely fixed with targeting SSE even for scalar code now. |