| ... | ... | @@ -1327,6 +1327,50 @@ test "lossyCast" { |
| 1327 | 1327 | try testing.expect(lossyCast(u32, @as(f32, maxInt(u32))) == maxInt(u32)); |
| 1328 | 1328 | } |
| 1329 | 1329 | |
| 1330 | /// Performs linear interpolation between *a* and *b* based on *t*. |
| 1331 | /// *t* must be in range 0.0 to 1.0. Supports floats and vectors of floats. |
| 1332 | /// |
| 1333 | /// This does not guarantee returning *b* if *t* is 1 due to floating-point errors. |
| 1334 | /// This is monotonic. |
| 1335 | pub fn lerp(a: anytype, b: anytype, t: anytype) @TypeOf(a, b, t) { |
| 1336 | const Type = @TypeOf(a, b, t); |
| 1337 | |
| 1338 | switch (@typeInfo(Type)) { |
| 1339 | .Float, .ComptimeFloat => assert(t >= 0 and t <= 1), |
| 1340 | .Vector => |vector| { |
| 1341 | const lower_bound = @reduce(.And, t >= @splat(vector.len, @as(vector.child, 0))); |
| 1342 | const upper_bound = @reduce(.And, t <= @splat(vector.len, @as(vector.child, 1))); |
| 1343 | assert(lower_bound and upper_bound); |
| 1344 | }, |
| 1345 | else => comptime unreachable, |
| 1346 | } |
| 1347 | |
| 1348 | return @mulAdd(Type, b - a, t, a); |
| 1349 | } |
| 1350 | |
| 1351 | test "lerp" { |
| 1352 | try testing.expectEqual(@as(f64, 75), lerp(50, 100, 0.5)); |
| 1353 | try testing.expectEqual(@as(f32, 43.75), lerp(50, 25, 0.25)); |
| 1354 | try testing.expectEqual(@as(f64, -31.25), lerp(-50, 25, 0.25)); |
| 1355 | |
| 1356 | try testing.expectApproxEqRel(@as(f32, -7.16067345e+03), lerp(-10000.12345, -5000.12345, 0.56789), 1e-19); |
| 1357 | try testing.expectApproxEqRel(@as(f64, 7.010987590521e+62), lerp(0.123456789e-64, 0.123456789e64, 0.56789), 1e-33); |
| 1358 | |
| 1359 | try testing.expectEqual(@as(f32, 0.0), lerp(@as(f32, 1.0e8), 1.0, 1.0)); |
| 1360 | try testing.expectEqual(@as(f64, 0.0), lerp(@as(f64, 1.0e16), 1.0, 1.0)); |
| 1361 | try testing.expectEqual(@as(f32, 1.0), lerp(@as(f32, 1.0e7), 1.0, 1.0)); |
| 1362 | try testing.expectEqual(@as(f64, 1.0), lerp(@as(f64, 1.0e15), 1.0, 1.0)); |
| 1363 | |
| 1364 | try testing.expectEqual( |
| 1365 | lerp(@splat(3, @as(f32, 0)), @splat(3, @as(f32, 50)), @splat(3, @as(f32, 0.5))), |
| 1366 | @Vector(3, f32){ 25, 25, 25 }, |
| 1367 | ); |
| 1368 | try testing.expectEqual( |
| 1369 | lerp(@splat(3, @as(f64, 50)), @splat(3, @as(f64, 100)), @splat(3, @as(f64, 0.5))), |
| 1370 | @Vector(3, f64){ 75, 75, 75 }, |
| 1371 | ); |
| 1372 | } |
| 1373 | |
| 1330 | 1374 | /// Returns the maximum value of integer type T. |
| 1331 | 1375 | pub fn maxInt(comptime T: type) comptime_int { |
| 1332 | 1376 | const info = @typeInfo(T); |