| ... | @@ -1363,23 +1363,13 @@ test "lossyCast" { | ... | @@ -1363,23 +1363,13 @@ test "lossyCast" { |
| 1363 | } | 1363 | } |
| 1364 | | 1364 | |
| 1365 | /// Performs linear interpolation between *a* and *b* based on *t*. | 1365 | /// Performs linear interpolation between *a* and *b* based on *t*. |
| 1366 | /// *t* must be in range 0.0 to 1.0. Supports floats and vectors of floats. | 1366 | /// *t* ranges from 0.0 to 1.0, but may exceed these bounds. |
| | 1367 | /// Supports floats and vectors of floats. |
| 1367 | /// | 1368 | /// |
| 1368 | /// This does not guarantee returning *b* if *t* is 1 due to floating-point errors. | 1369 | /// This does not guarantee returning *b* if *t* is 1 due to floating-point errors. |
| 1369 | /// This is monotonic. | 1370 | /// This is monotonic. |
| 1370 | pub fn lerp(a: anytype, b: anytype, t: anytype) @TypeOf(a, b, t) { | 1371 | pub fn lerp(a: anytype, b: anytype, t: anytype) @TypeOf(a, b, t) { |
| 1371 | const Type = @TypeOf(a, b, t); | 1372 | const Type = @TypeOf(a, b, t); |
| 1372 | | | |
| 1373 | switch (@typeInfo(Type)) { | | |
| 1374 | .Float, .ComptimeFloat => assert(t >= 0 and t <= 1), | | |
| 1375 | .Vector => { | | |
| 1376 | const lower_bound = @reduce(.And, t >= @as(Type, @splat(0))); | | |
| 1377 | const upper_bound = @reduce(.And, t <= @as(Type, @splat(1))); | | |
| 1378 | assert(lower_bound and upper_bound); | | |
| 1379 | }, | | |
| 1380 | else => comptime unreachable, | | |
| 1381 | } | | |
| 1382 | | | |
| 1383 | return @mulAdd(Type, b - a, t, a); | 1373 | return @mulAdd(Type, b - a, t, a); |
| 1384 | } | 1374 | } |
| 1385 | | 1375 | |
| ... | @@ -1392,6 +1382,9 @@ test "lerp" { | ... | @@ -1392,6 +1382,9 @@ test "lerp" { |
| 1392 | try testing.expectEqual(@as(f32, 43.75), lerp(50, 25, 0.25)); | 1382 | try testing.expectEqual(@as(f32, 43.75), lerp(50, 25, 0.25)); |
| 1393 | try testing.expectEqual(@as(f64, -31.25), lerp(-50, 25, 0.25)); | 1383 | try testing.expectEqual(@as(f64, -31.25), lerp(-50, 25, 0.25)); |
| 1394 | | 1384 | |
| | 1385 | try testing.expectEqual(@as(f64, 30), lerp(10, 20, 2.0)); |
| | 1386 | try testing.expectEqual(@as(f64, 5), lerp(10, 20, -0.5)); |
| | 1387 | |
| 1395 | try testing.expectApproxEqRel(@as(f32, -7.16067345e+03), lerp(-10000.12345, -5000.12345, 0.56789), 1e-19); | 1388 | try testing.expectApproxEqRel(@as(f32, -7.16067345e+03), lerp(-10000.12345, -5000.12345, 0.56789), 1e-19); |
| 1396 | try testing.expectApproxEqRel(@as(f64, 7.010987590521e+62), lerp(0.123456789e-64, 0.123456789e64, 0.56789), 1e-33); | 1389 | try testing.expectApproxEqRel(@as(f64, 7.010987590521e+62), lerp(0.123456789e-64, 0.123456789e64, 0.56789), 1e-33); |
| 1397 | | 1390 | |
| ... | @@ -1405,8 +1398,8 @@ test "lerp" { | ... | @@ -1405,8 +1398,8 @@ test "lerp" { |
| 1405 | const b: @Vector(3, f32) = @splat(50); | 1398 | const b: @Vector(3, f32) = @splat(50); |
| 1406 | const t: @Vector(3, f32) = @splat(0.5); | 1399 | const t: @Vector(3, f32) = @splat(0.5); |
| 1407 | try testing.expectEqual( | 1400 | try testing.expectEqual( |
| 1408 | lerp(a, b, t), | | |
| 1409 | @Vector(3, f32){ 25, 25, 25 }, | 1401 | @Vector(3, f32){ 25, 25, 25 }, |
| | 1402 | lerp(a, b, t), |
| 1410 | ); | 1403 | ); |
| 1411 | } | 1404 | } |
| 1412 | { | 1405 | { |
| ... | @@ -1414,8 +1407,17 @@ test "lerp" { | ... | @@ -1414,8 +1407,17 @@ test "lerp" { |
| 1414 | const b: @Vector(3, f64) = @splat(100); | 1407 | const b: @Vector(3, f64) = @splat(100); |
| 1415 | const t: @Vector(3, f64) = @splat(0.5); | 1408 | const t: @Vector(3, f64) = @splat(0.5); |
| 1416 | try testing.expectEqual( | 1409 | try testing.expectEqual( |
| 1417 | lerp(a, b, t), | | |
| 1418 | @Vector(3, f64){ 75, 75, 75 }, | 1410 | @Vector(3, f64){ 75, 75, 75 }, |
| | 1411 | lerp(a, b, t), |
| | 1412 | ); |
| | 1413 | } |
| | 1414 | { |
| | 1415 | const a: @Vector(2, f32) = @splat(40); |
| | 1416 | const b: @Vector(2, f32) = @splat(80); |
| | 1417 | const t: @Vector(2, f32) = @Vector(2, f32){ 0.25, 0.75 }; |
| | 1418 | try testing.expectEqual( |
| | 1419 | @Vector(2, f32){ 50, 70 }, |
| | 1420 | lerp(a, b, t), |
| 1419 | ); | 1421 | ); |
| 1420 | } | 1422 | } |
| 1421 | } | 1423 | } |