Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions lib/ui/lerp.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,21 @@ double? lerpDouble(num? a, num? b, double t) {
assert(a.isFinite, 'Cannot interpolate between finite and non-finite values');
assert(b.isFinite, 'Cannot interpolate between finite and non-finite values');
assert(t.isFinite, 't must be finite when interpolating between values');
return a + (b - a) * t as double;
return a * (1.0 - t) + b * t as double;
}

/// Linearly interpolate between two doubles.
///
/// Same as [lerpDouble] but specialized for non-null `double` type.
double _lerpDouble(double a, double b, double t) {
return a + (b - a) * t;
return a * (1.0 - t) + b * t;
}

/// Linearly interpolate between two integers.
///
/// Same as [lerpDouble] but specialized for non-null `int` type.
double _lerpInt(int a, int b, double t) {
return a + (b - a) * t;
return a * (1.0 - t) + b * t;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this one doesn't need it

}

/// Same as [num.clamp] but specialized for non-null [int].
Expand Down
41 changes: 25 additions & 16 deletions testing/dart/lerp_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,19 @@ void main() {
});

test('lerpDouble should treat a null input as 0 if the other input is non-null', () {
expect(lerpDouble(null, 10.0, 0.25), 2.5);
expect(lerpDouble(10.0, null, 0.25), 7.5);
expect(lerpDouble(null, 10.0, 0.25), closeTo(2.5, precisionErrorTolerance));
expect(lerpDouble(10.0, null, 0.25), closeTo(7.5, precisionErrorTolerance));

expect(lerpDouble(null, 10, 0.25), 2.5);
expect(lerpDouble(10, null, 0.25), 7.5);
expect(lerpDouble(null, 10, 0.25), closeTo(2.5, precisionErrorTolerance));
expect(lerpDouble(10, null, 0.25), closeTo(7.5, precisionErrorTolerance));
});

test('lerpDouble should handle interpolation values < 0.0', () {
expect(lerpDouble(0.0, 10.0, -5.0), -50.0);
expect(lerpDouble(10.0, 0.0, -5.0), 60.0);
expect(lerpDouble(0.0, 10.0, -5.0), closeTo(-50.0, precisionErrorTolerance));
expect(lerpDouble(10.0, 0.0, -5.0), closeTo(60.0, precisionErrorTolerance));

expect(lerpDouble(0, 10, -5), -50);
expect(lerpDouble(10, 0, -5), 60);
expect(lerpDouble(0, 10, -5), closeTo(-50, precisionErrorTolerance));
expect(lerpDouble(10, 0, -5), closeTo(60, precisionErrorTolerance));
});

test('lerpDouble should return the start value at 0.0', () {
Expand All @@ -44,11 +44,17 @@ void main() {
});

test('lerpDouble should interpolate between two values', () {
expect(lerpDouble(0.0, 10.0, 0.25), 2.5);
expect(lerpDouble(10.0, 0.0, 0.25), 7.5);
expect(lerpDouble(0.0, 10.0, 0.25), closeTo(2.5, precisionErrorTolerance));
expect(lerpDouble(10.0, 0.0, 0.25), closeTo(7.5, precisionErrorTolerance));

expect(lerpDouble(0, 10, 0.25), 2.5);
expect(lerpDouble(10, 0, 0.25), 7.5);
expect(lerpDouble(0, 10, 0.25), closeTo(2.5, precisionErrorTolerance));
expect(lerpDouble(10, 0, 0.25), closeTo(7.5, precisionErrorTolerance));

// Exact answer: 20.0 - 1.0e-29
expect(lerpDouble(10.0, 1.0e30, 1.0e-29), closeTo(20.0, precisionErrorTolerance));

// Exact answer: 5.0 + 5.0e29
expect(lerpDouble(10.0, 1.0e30, 0.5), closeTo(5.0e29, precisionErrorTolerance));
});

test('lerpDouble should return the end value at 1.0', () {
Expand All @@ -57,14 +63,17 @@ void main() {

expect(lerpDouble(0, 10, 5), 50);
expect(lerpDouble(10, 0, 5), -40);

expect(lerpDouble(1.0e30, 10.0, 1.0), 10.0);
expect(lerpDouble(10.0, 1.0e30, 0.0), 10.0);
});

test('lerpDouble should handle interpolation values > 1.0', () {
expect(lerpDouble(0.0, 10.0, 5.0), 50.0);
expect(lerpDouble(10.0, 0.0, 5.0), -40.0);
expect(lerpDouble(0.0, 10.0, 5.0), closeTo(50.0, precisionErrorTolerance));
expect(lerpDouble(10.0, 0.0, 5.0), closeTo(-40.0, precisionErrorTolerance));

expect(lerpDouble(0, 10, 5), 50);
expect(lerpDouble(10, 0, 5), -40);
expect(lerpDouble(0, 10, 5), closeTo(50, precisionErrorTolerance));
expect(lerpDouble(10, 0, 5), closeTo(-40, precisionErrorTolerance));
});

test('lerpDouble should return input value in all cases if begin/end are equal', () {
Expand Down
7 changes: 7 additions & 0 deletions testing/dart/test_util.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@

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
Expand Down