authorgravatar for 77922942+expikr@users.noreply.github.comexpikr <77922942+expikr@users.noreply.github.com> 2024-03-15 07:31:02-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-03-15 16:31:02+02:00
log67a40c679d5bdbfb989a196e0410204ea8e787f7
tree91ec7f0a4f43f77cff92bf91f1f446fa115fb500
parenta4508ad7167513d178fd237e4cd361185800d05d
signaturebadge-check Signed by PGP key B5690EEEBB952194

make `math.degreesToRadians` and `math.radiansToDegrees` infer type from argument


1 files changed, 62 insertions(+), 20 deletions(-)

lib/std/math.zig+62-20
...@@ -37,6 +37,12 @@ pub const sqrt2 = 1.414213562373095048801688724209698079;...@@ -37,6 +37,12 @@ pub const sqrt2 = 1.414213562373095048801688724209698079;
37/// 1/sqrt(2)37/// 1/sqrt(2)
38pub const sqrt1_2 = 0.707106781186547524400844362104849039;38pub const sqrt1_2 = 0.707106781186547524400844362104849039;
3939
40/// pi/180.0
41pub const rad_per_deg = 0.0174532925199432957692369076848861271344287188854172545609719144;
42
43/// 180.0/pi
44pub const deg_per_rad = 57.295779513082320876798154814105170332405472466564321549160243861;
45
40pub const floatExponentBits = @import("math/float.zig").floatExponentBits;46pub const floatExponentBits = @import("math/float.zig").floatExponentBits;
41pub const floatMantissaBits = @import("math/float.zig").floatMantissaBits;47pub const floatMantissaBits = @import("math/float.zig").floatMantissaBits;
42pub const floatFractionalBits = @import("math/float.zig").floatFractionalBits;48pub const floatFractionalBits = @import("math/float.zig").floatFractionalBits;
...@@ -293,32 +299,68 @@ pub inline fn tan(value: anytype) @TypeOf(value) {...@@ -293,32 +299,68 @@ pub inline fn tan(value: anytype) @TypeOf(value) {
293 return @tan(value);299 return @tan(value);
294}300}
295301
296/// Converts an angle in radians to degrees. T must be a float type.302/// Converts an angle in radians to degrees. T must be a float or comptime number or a vector of floats.
297pub fn radiansToDegrees(comptime T: type, angle_in_radians: T) T {303pub fn radiansToDegrees(ang: anytype) if (@TypeOf(ang) == comptime_int) comptime_float else @TypeOf(ang) {
298 if (@typeInfo(T) != .Float and @typeInfo(T) != .ComptimeFloat)304 const T = @TypeOf(ang);
299 @compileError("T must be a float type");305 switch (@typeInfo(T)) {
300 return angle_in_radians * 180.0 / pi;306 .Float, .ComptimeFloat, .ComptimeInt => return ang * deg_per_rad,
307 .Vector => |V| if (@typeInfo(V.child) == .Float) return ang * @as(T, @splat(deg_per_rad)),
308 else => {},
309 }
310 @compileError("Input must be float or a comptime number, or a vector of floats.");
301}311}
302312
303test "radiansToDegrees" {313test "radiansToDegrees" {
304 try std.testing.expectApproxEqAbs(@as(f32, 0), radiansToDegrees(f32, 0), 1e-6);314 const zero: f32 = 0;
305 try std.testing.expectApproxEqAbs(@as(f32, 90), radiansToDegrees(f32, pi / 2.0), 1e-6);315 const half_pi: f32 = pi / 2.0;
306 try std.testing.expectApproxEqAbs(@as(f32, -45), radiansToDegrees(f32, -pi / 4.0), 1e-6);316 const neg_quart_pi: f32 = -pi / 4.0;
307 try std.testing.expectApproxEqAbs(@as(f32, 180), radiansToDegrees(f32, pi), 1e-6);317 const one_pi: f32 = pi;
308 try std.testing.expectApproxEqAbs(@as(f32, 360), radiansToDegrees(f32, 2.0 * pi), 1e-6);318 const two_pi: f32 = 2.0 * pi;
309}319 try std.testing.expectApproxEqAbs(@as(f32, 0), radiansToDegrees(zero), 1e-6);
310320 try std.testing.expectApproxEqAbs(@as(f32, 90), radiansToDegrees(half_pi), 1e-6);
311/// Converts an angle in degrees to radians. T must be a float type.321 try std.testing.expectApproxEqAbs(@as(f32, -45), radiansToDegrees(neg_quart_pi), 1e-6);
312pub fn degreesToRadians(comptime T: type, angle_in_degrees: T) T {322 try std.testing.expectApproxEqAbs(@as(f32, 180), radiansToDegrees(one_pi), 1e-6);
313 if (@typeInfo(T) != .Float and @typeInfo(T) != .ComptimeFloat)323 try std.testing.expectApproxEqAbs(@as(f32, 360), radiansToDegrees(two_pi), 1e-6);
314 @compileError("T must be a float type");324
315 return angle_in_degrees * pi / 180.0;325 const result = radiansToDegrees(@Vector(4, f32){
326 half_pi,
327 neg_quart_pi,
328 one_pi,
329 two_pi,
330 });
331 try std.testing.expectApproxEqAbs(@as(f32, 90), result[0], 1e-6);
332 try std.testing.expectApproxEqAbs(@as(f32, -45), result[1], 1e-6);
333 try std.testing.expectApproxEqAbs(@as(f32, 180), result[2], 1e-6);
334 try std.testing.expectApproxEqAbs(@as(f32, 360), result[3], 1e-6);
335}
336
337/// Converts an angle in degrees to radians. T must be a float or comptime number or a vector of floats.
338pub fn degreesToRadians(ang: anytype) if (@TypeOf(ang) == comptime_int) comptime_float else @TypeOf(ang) {
339 const T = @TypeOf(ang);
340 switch (@typeInfo(T)) {
341 .Float, .ComptimeFloat, .ComptimeInt => return ang * rad_per_deg,
342 .Vector => |V| if (@typeInfo(V.child) == .Float) return ang * @as(T, @splat(rad_per_deg)),
343 else => {},
344 }
345 @compileError("Input must be float or a comptime number, or a vector of floats.");
316}346}
317347
318test "degreesToRadians" {348test "degreesToRadians" {
319 try std.testing.expectApproxEqAbs(@as(f32, pi / 2.0), degreesToRadians(f32, 90), 1e-6);349 const ninety: f32 = 90;
320 try std.testing.expectApproxEqAbs(@as(f32, -3 * pi / 2.0), degreesToRadians(f32, -270), 1e-6);350 const neg_two_seventy: f32 = -270;
321 try std.testing.expectApproxEqAbs(@as(f32, 2 * pi), degreesToRadians(f32, 360), 1e-6);351 const three_sixty: f32 = 360;
352 try std.testing.expectApproxEqAbs(@as(f32, pi / 2.0), degreesToRadians(ninety), 1e-6);
353 try std.testing.expectApproxEqAbs(@as(f32, -3 * pi / 2.0), degreesToRadians(neg_two_seventy), 1e-6);
354 try std.testing.expectApproxEqAbs(@as(f32, 2 * pi), degreesToRadians(three_sixty), 1e-6);
355
356 const result = degreesToRadians(@Vector(3, f32){
357 ninety,
358 neg_two_seventy,
359 three_sixty,
360 });
361 try std.testing.expectApproxEqAbs(@as(f32, pi / 2.0), result[0], 1e-6);
362 try std.testing.expectApproxEqAbs(@as(f32, -3 * pi / 2.0), result[1], 1e-6);
363 try std.testing.expectApproxEqAbs(@as(f32, 2 * pi), result[2], 1e-6);
322}364}
323365
324/// Base-e exponential function on a floating point number.366/// Base-e exponential function on a floating point number.