-
由 Chris Bracken 提交于
This updates the web_ui implementation of lerpDouble to match the behaviour of the C++ engine implementation in dart:ui. Specifically this covers the following changes: * #20871: stricter handling of NaN and infinity * #20879: Improve the precision of lerpDouble lerpDouble: stricter handling of NaN and infinity (#20871) ---------------------------------------------------------- Previously, the behaviour of lerpDouble with respect to NaN and infinity was relatively complex and difficult to reason about. This patch simplifies the behaviour with respect to those conditions and adds documentation and tests. In general, if `a == b` or both values are null, infinite, or NaN, `a` is returned. Otherwise we require `a` and `b` and `t` to be finite or null and the result of the linear interpolation is returned. Improve the precision of lerpDouble (#20879) -------------------------------------------- Reduces errors caused by the loss of floating point precision when the two extrema of the lerp differ significantly in magnitude. Previously, we used the calculation: a + (b - a) * t When the difference in magnitude between `a` and `b` exceeds the precision representable by double-precision floating point math, `b - a` results in the larger-magnitude value of `a` or `b`. The error between the value produced and the correct value is then scaled by t. A simple example of the impact can be seen when `a` is significantly larger in magnitude than `b`. In that case, `b - a` results in `a` and when `t` is 1.0, the resulting value is `a - (a) * 1.0 == 0`. The patch transforms the computation to the mathematically-equivalent expression: a * (1.0 - t) + b * t By scaling each value independently, the behaviour is more accurate. From the point of view of performance, this adds an extra multiplication, but multiplication is relatively cheap and the behaviour is significantly better. This patch also adds a `precisionErrorTolerance` constant to test_utils.dart and migrates existing tests to use `closeTo()` for testing. The tests themselves *do* currently use values that have an exact floating-point representation, but we should allow for flexibility in future implementation changes.
cf8c6b8b