mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
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.
52 lines
1.4 KiB
Dart
52 lines
1.4 KiB
Dart
// Copyright 2013 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
// @dart = 2.6
|
|
|
|
import 'package:test/test.dart';
|
|
|
|
/// The epsilon of tolerable double precision error.
|
|
///
|
|
/// This is used in various places in the framework to allow for floating point
|
|
/// precision loss in calculations. Differences below this threshold are safe
|
|
/// to disregard.
|
|
const double precisionErrorTolerance = 1e-10;
|
|
|
|
/// Asserts that `callback` throws an [AssertionError].
|
|
///
|
|
/// When running in a VM in which assertions are enabled, asserts that the
|
|
/// specified callback throws an [AssertionError]. When asserts are not
|
|
/// enabled, such as when running using a release-mode VM with default
|
|
/// settings, this acts as a no-op.
|
|
void expectAssertion(Function callback) {
|
|
bool assertsEnabled = false;
|
|
assert(() {
|
|
assertsEnabled = true;
|
|
return true;
|
|
}());
|
|
if (assertsEnabled) {
|
|
bool threw = false;
|
|
try {
|
|
callback();
|
|
} catch (e) {
|
|
expect(e is AssertionError, true);
|
|
threw = true;
|
|
}
|
|
expect(threw, true);
|
|
}
|
|
}
|
|
|
|
/// Asserts that `callback` throws an [ArgumentError].
|
|
void expectArgumentError(Function callback) {
|
|
bool threw = false;
|
|
try {
|
|
callback();
|
|
} catch (e) {
|
|
expect(e is ArgumentError, true);
|
|
threw = true;
|
|
}
|
|
expect(threw, true);
|
|
}
|
|
|