last day (16 days later) » 

20:01
15
A: How can I perform a deterministic physics simulation?

TheraotI will end up saying to use fixed point number. However, this is a ride I am taking you on. To be clear, if you can use a compiler that lets you specify how floating points works you can do that. That is not always an option. Besides, we are doing this for determinism. Fixed point numbers does n...

As an embedded engineer who's done a fair amount of fixed-point processing, I totally recommend not using it. Fixed-point processing always has rounding errors in converting to fixed-point, and in all the calculations you do. These rounding errors are constant, whereas rounding errors in floating-point are variable size. The floating-point errors can only ever be smaller than or equal to fixed-point errors with the same mantissa. So it's "solving" a problem which doesn't really exist, by adding problems which are worse.
... Plus the work involved in tracking the range and binary point for each step of the calculations is a complete pain and is immensely prone to errors. You would need a really good reason to do this, and the only possible good reason is that your processor is slow and doesn't have floating-point support.
The part about reordering from the CPU is wrong. The CPU doesn't do reordering by jumping around in the code, if an earlier instruction (in program order) is eligible for dispatching before an older one (in program order) then the two are in different dependency chain. The CPU won't transform a + b + c + d into (a + b) + (c + d), the compiler will*/*could (it's a form of vectorization). If you can tell your compiler to use strict FP rules and target only IEEE754 architectures (configured the same way) you should be fine. That's why IEEE754 exists in the first place.
@Graham I am normally quite critical of fixed-point too and say that people who think it's better than floating-point in some way just have not understood floats or, indeed, real numbers. However, I think in this application they could actually make sense, and the answer explains quite well why.
@leftaroundabout The problem is that the answerer hasn't really understood it. In fixed-point, sure, 12.34+23.45=35.79 exactly. The problem is that the two terms may actually be 12.378 and 23.4539, and the process of truncating to fixed-point creates errors which are worse than or equal to anything which the floating-point calculation can do.
@Graham in properly-implemented fixed point, 123.456+234.55 is a type error that could never make it to the runtime in the first place. Or, where are you going with this?
20:01
@leftaroundabout Hit return too early. :)
@Graham ok. I see you're argument, I've myself made it a couple of times in the past, to people who thought fixed-point would be good for physics. It's not. However, the OP doesn't really care about good for physics (up to some point), nor about performance (up to some point) they care mostly about binary deterministic – whatever behaviour, no matter how bad physics-wise, should be exactly the same in a repeated program run. And for that, integers are much easier to reason about.
@leftaroundabout I guess easier to see at a glance. But IEEE-754 is still deterministic, and the rules are well defined (since it's a standard).
To those saying floating point might work because IEEE-754 is deterministic and defines how we should perform these operations, that's only true for +, - *, /, and sqrt. A physics engine needs trigonometric operations too. Also, I would love to think that solving this problem was as simple as using compiler flags, but from what I have read through heavy research lately, it's simply not enough and you're not thinking of everything. It looks like people in my position eventually go with fixed point numbers.
This blog is about someone in a similar position to me and why he eventually chose fixed point precision: Contraption Maker
"IEEE-754 is deterministic and defines how we should perform these operations, that's only true for +, - *, /, and sqrt" - Actually it's not even true for those operations. The standard allows them to be done at a higher precision than the data-type, and in fact that's exactly what x86 does (it uses 80-bit FP registers). Thus, even without operation reordering, the result of a statement like f*a+b depends on when the compiler decides to round back down to 64-bit.. which (in C and C++) can change arbitrarily between builds.
@jvn91173 True, but there are various polynomial approximations for trig. Taylor is the simplest, and CORDIC is popular. Based on OlliW's work though, you can do a sin/cos approximation which is a C2 continuous 6th-order polynomial fit with 6e-6 worst-case error. Going up to 7th-order got me around 1e-13 error, and 8th-order was something like 1e-23. I'll post details next week if you like. OlliW's original work is at olliw.eu/2014/fast-functions and I used the basic concept to add more accuracy.
@jvn91173 Re the Butterfly Effect article, what he hasn't mentioned is that by going integer, he has imposed significant limitations on voxel resolution and universe size on his engine. For him it doesn't matter, but you need to check on yours. If you want mm resolution on voxels, 32-bit ints only get you 4.3km of game area, so you probably need to go 64-bit for your positioning.

  last day (16 days later) »