• C
    Update web lerpDouble to match C++ behaviour (#21010) · cf8c6b8b
    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
lerp_test.dart 5.6 KB