| ... | @@ -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) |
| 38 | pub const sqrt1_2 = 0.707106781186547524400844362104849039; | 38 | pub const sqrt1_2 = 0.707106781186547524400844362104849039; |
| 39 | | 39 | |
| | 40 | /// pi/180.0 |
| | 41 | pub const rad_per_deg = 0.0174532925199432957692369076848861271344287188854172545609719144; |
| | 42 | |
| | 43 | /// 180.0/pi |
| | 44 | pub const deg_per_rad = 57.295779513082320876798154814105170332405472466564321549160243861; |
| | 45 | |
| 40 | pub const floatExponentBits = @import("math/float.zig").floatExponentBits; | 46 | pub const floatExponentBits = @import("math/float.zig").floatExponentBits; |
| 41 | pub const floatMantissaBits = @import("math/float.zig").floatMantissaBits; | 47 | pub const floatMantissaBits = @import("math/float.zig").floatMantissaBits; |
| 42 | pub const floatFractionalBits = @import("math/float.zig").floatFractionalBits; | 48 | pub 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 | } |
| 295 | | 301 | |
| 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. |
| 297 | pub fn radiansToDegrees(comptime T: type, angle_in_radians: T) T { | 303 | pub 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 | } |
| 302 | | 312 | |
| 303 | test "radiansToDegrees" { | 313 | test "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); |
| 310 | | 320 | 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); |
| 312 | pub 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. |
| | 338 | pub 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 | } |
| 317 | | 347 | |
| 318 | test "degreesToRadians" { | 348 | test "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 | } |
| 323 | | 365 | |
| 324 | /// Base-e exponential function on a floating point number. | 366 | /// Base-e exponential function on a floating point number. |