Skip to content

Commit 62662ab

Browse files
author
zooster
committed
std.math: add lerp
1 parent 710e2e7 commit 62662ab

File tree

1 file changed

+27
-0
lines changed

1 file changed

+27
-0
lines changed

lib/std/math.zig

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1312,6 +1312,33 @@ test "lossyCast" {
13121312
try testing.expect(lossyCast(u32, @as(f32, maxInt(u32))) == maxInt(u32));
13131313
}
13141314

1315+
/// Performs linear interpolation between *a* and *b* based on *t*.
1316+
/// *t* must be in range 0.0 to 1.0. T must be a float type.
1317+
///
1318+
/// This does not guarantee returning *b* if *t* is 1 due to floating-point errors.
1319+
/// This is monotonic.
1320+
pub fn lerp(comptime T: type, a: T, b: T, t: T) T {
1321+
if (@typeInfo(T) != .Float and @typeInfo(T) != .ComptimeFloat)
1322+
@compileError("T must be a float type");
1323+
1324+
assert(t >= 0 and t <= 1);
1325+
return @mulAdd(T, b - a, t, a);
1326+
}
1327+
1328+
test "lerp" {
1329+
try testing.expectEqual(@as(f16, 75), lerp(f16, 50, 100, 0.5));
1330+
try testing.expectEqual(@as(f32, 43.75), lerp(f32, 50, 25, 0.25));
1331+
try testing.expectEqual(@as(f64, -31.25), lerp(f64, -50, 25, 0.25));
1332+
try testing.expectApproxEqRel(@as(f80, -7.16067345e+03), lerp(f80, -10000.12345, -5000.12345, 0.56789), 1e-19);
1333+
try testing.expectApproxEqRel(@as(f128, 7.010987590521e+62), lerp(f128, 0.123456789e-64, 0.123456789e64, 0.56789), 1e-33);
1334+
1335+
// this highlights the precision
1336+
try testing.expectEqual(@as(f32, 0.0), lerp(f32, 1.0e8, 1.0, 1.0));
1337+
try testing.expectEqual(@as(f16, 0.0), lerp(f16, 1.0e4, 1.0, 1.0));
1338+
try testing.expectEqual(@as(f32, 1.0), lerp(f32, 1.0e7, 1.0, 1.0));
1339+
try testing.expectEqual(@as(f16, 1.0), lerp(f16, 1.0e3, 1.0, 1.0));
1340+
}
1341+
13151342
/// Returns the maximum value of integer type T.
13161343
pub fn maxInt(comptime T: type) comptime_int {
13171344
const info = @typeInfo(T);

0 commit comments

Comments
 (0)