From f335d92b28e02f8c3efa2f814e72966e0c53565f Mon Sep 17 00:00:00 2001 From: matu3ba Date: Sat, 21 Oct 2023 11:12:02 +0200 Subject: [PATCH] compiler_rt: arm frsub, drsub with tests (#17629) Tests with +-0, numbers with accuracy 0.001, 0.000001, +-max for inf. --- lib/compiler_rt/arm.zig | 66 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/lib/compiler_rt/arm.zig b/lib/compiler_rt/arm.zig index 194256db3c..217625b2f7 100644 --- a/lib/compiler_rt/arm.zig +++ b/lib/compiler_rt/arm.zig @@ -40,7 +40,8 @@ comptime { @export(__aeabi_read_tp, .{ .name = "__aeabi_read_tp", .linkage = common.linkage, .visibility = common.visibility }); } - // floating-point helper functions (double-precision reverse subtraction, y – x), see subdf3.zig + // floating-point helper functions (single+double-precision reverse subtraction, y – x), see subdf3.zig + @export(__aeabi_frsub, .{ .name = "__aeabi_frsub", .linkage = common.linkage, .visibility = common.visibility }); @export(__aeabi_drsub, .{ .name = "__aeabi_drsub", .linkage = common.linkage, .visibility = common.visibility }); } } @@ -191,7 +192,68 @@ pub fn __aeabi_ldivmod() callconv(.Naked) void { unreachable; } -pub fn __aeabi_drsub(a: f64, b: f64) callconv(.AAPCS) f64 { +// Float Arithmetic + +fn __aeabi_frsub(a: f32, b: f32) callconv(.AAPCS) f32 { + const neg_a: f32 = @bitCast(@as(u32, @bitCast(a)) ^ (@as(u32, 1) << 31)); + return b + neg_a; +} + +fn __aeabi_drsub(a: f64, b: f64) callconv(.AAPCS) f64 { const neg_a: f64 = @bitCast(@as(u64, @bitCast(a)) ^ (@as(u64, 1) << 63)); return b + neg_a; } + +test "__aeabi_frsub" { + if (!builtin.cpu.arch.isARM()) return error.SkipZigTest; + const inf32 = std.math.inf(f32); + const maxf32 = std.math.floatMax(f32); + const frsub_data = [_][3]f32{ + [_]f32{ 0.0, 0.0, -0.0 }, + [_]f32{ 0.0, -0.0, -0.0 }, + [_]f32{ -0.0, 0.0, 0.0 }, + [_]f32{ -0.0, -0.0, -0.0 }, + [_]f32{ 0.0, 1.0, 1.0 }, + [_]f32{ 1.0, 0.0, -1.0 }, + [_]f32{ 1.0, 1.0, 0.0 }, + [_]f32{ 1234.56789, 9876.54321, 8641.97532 }, + [_]f32{ 9876.54321, 1234.56789, -8641.97532 }, + [_]f32{ -8641.97532, 1234.56789, 9876.54321 }, + [_]f32{ 8641.97532, 9876.54321, 1234.56789 }, + [_]f32{ -maxf32, -maxf32, 0.0 }, + [_]f32{ maxf32, maxf32, 0.0 }, + [_]f32{ maxf32, -maxf32, -inf32 }, + [_]f32{ -maxf32, maxf32, inf32 }, + }; + if (!builtin.cpu.arch.isARM()) return error.SkipZigTest; + for (frsub_data) |data| { + try std.testing.expectApproxEqAbs(data[2], __aeabi_frsub(data[0], data[1]), 0.001); + } +} + +test "__aeabi_drsub" { + if (!builtin.cpu.arch.isARM()) return error.SkipZigTest; + const inf64 = std.math.inf(f64); + const maxf64 = std.math.floatMax(f64); + const frsub_data = [_][3]f64{ + [_]f64{ 0.0, 0.0, -0.0 }, + [_]f64{ 0.0, -0.0, -0.0 }, + [_]f64{ -0.0, 0.0, 0.0 }, + [_]f64{ -0.0, -0.0, -0.0 }, + [_]f64{ 0.0, 1.0, 1.0 }, + [_]f64{ 1.0, 0.0, -1.0 }, + [_]f64{ 1.0, 1.0, 0.0 }, + [_]f64{ 1234.56789, 9876.54321, 8641.97532 }, + [_]f64{ 9876.54321, 1234.56789, -8641.97532 }, + [_]f64{ -8641.97532, 1234.56789, 9876.54321 }, + [_]f64{ 8641.97532, 9876.54321, 1234.56789 }, + [_]f64{ -maxf64, -maxf64, 0.0 }, + [_]f64{ maxf64, maxf64, 0.0 }, + [_]f64{ maxf64, -maxf64, -inf64 }, + [_]f64{ -maxf64, maxf64, inf64 }, + }; + if (!builtin.cpu.arch.isARM()) return error.SkipZigTest; + for (frsub_data) |data| { + try std.testing.expectApproxEqAbs(data[2], __aeabi_drsub(data[0], data[1]), 0.000001); + } +}