Commit e10c0eefde

Jan Philipp Hafer <jan.hafer@rwth-aachen.de>
2023-02-11 13:36:33
compiler_rt: add __powihf2, __powisf2, __powidf2, __powitf2, __powixf2
Implementation and tests ported from LLVM release 80. Tests of __powihf2 created from __powisf2 tests with minor adjustments.
1 parent ca05282
lib/compiler_rt/powiXf2.zig
@@ -0,0 +1,58 @@
+//! a raised to integer power of b
+//! ported from https://github.com/llvm-mirror/compiler-rt/blob/release_80/lib/builtins/powisf2.c
+//! Multiplication order (left-to-right or right-to-left) does not matter for
+//! error propagation and this method is optimized for performance, not accuracy.
+
+const builtin = @import("builtin");
+const common = @import("common.zig");
+const std = @import("std");
+
+pub const panic = common.panic;
+
+comptime {
+    @export(__powihf2, .{ .name = "__powihf2", .linkage = common.linkage, .visibility = common.visibility });
+    @export(__powisf2, .{ .name = "__powisf2", .linkage = common.linkage, .visibility = common.visibility });
+    @export(__powidf2, .{ .name = "__powidf2", .linkage = common.linkage, .visibility = common.visibility });
+    @export(__powitf2, .{ .name = "__powitf2", .linkage = common.linkage, .visibility = common.visibility });
+    @export(__powixf2, .{ .name = "__powixf2", .linkage = common.linkage, .visibility = common.visibility });
+}
+
+inline fn powiXf2(comptime FT: type, a: FT, b: i32) FT {
+    var x_a: FT = a;
+    var x_b: i32 = b;
+    const is_recip: bool = b < 0;
+    var r: FT = 1.0;
+    while (true) {
+        if (@bitCast(u32, x_b) & @as(u32, 1) != 0) {
+            r *= x_a;
+        }
+        x_b = @divTrunc(x_b, @as(i32, 2));
+        if (x_b == 0) break;
+        x_a *= x_a; // Multiplication of x_a propagates the error
+    }
+    return if (is_recip) 1 / r else r;
+}
+
+pub fn __powihf2(a: f16, b: i32) callconv(.C) f16 {
+    return powiXf2(f16, a, b);
+}
+
+pub fn __powisf2(a: f32, b: i32) callconv(.C) f32 {
+    return powiXf2(f32, a, b);
+}
+
+pub fn __powidf2(a: f64, b: i32) callconv(.C) f64 {
+    return powiXf2(f64, a, b);
+}
+
+pub fn __powitf2(a: f128, b: i32) callconv(.C) f128 {
+    return powiXf2(f128, a, b);
+}
+
+pub fn __powixf2(a: f80, b: i32) callconv(.C) f80 {
+    return powiXf2(f80, a, b);
+}
+
+test {
+    _ = @import("powiXf2_test.zig");
+}
lib/compiler_rt/powiXf2_test.zig
@@ -0,0 +1,556 @@
+// ported from https://github.com/llvm-mirror/compiler-rt/blob/release_80/test/builtins/Unit/
+// powisf2_test.c, powidf2_test.c, powitf2_test.c, powixf2_test.c
+// powihf2 adapted from powisf2 tests
+
+const powiXf2 = @import("powiXf2.zig");
+const testing = @import("std").testing;
+const math = @import("std").math;
+
+fn test__powihf2(a: f16, b: i32, expected: f16) !void {
+    var result = powiXf2.__powihf2(a, b);
+    try testing.expectEqual(expected, result);
+}
+
+fn test__powisf2(a: f32, b: i32, expected: f32) !void {
+    var result = powiXf2.__powisf2(a, b);
+    try testing.expectEqual(expected, result);
+}
+
+fn test__powidf2(a: f64, b: i32, expected: f64) !void {
+    var result = powiXf2.__powidf2(a, b);
+    try testing.expectEqual(expected, result);
+}
+
+fn test__powitf2(a: f128, b: i32, expected: f128) !void {
+    var result = powiXf2.__powitf2(a, b);
+    try testing.expectEqual(expected, result);
+}
+
+fn test__powixf2(a: f80, b: i32, expected: f80) !void {
+    var result = powiXf2.__powixf2(a, b);
+    try testing.expectEqual(expected, result);
+}
+
+test "powihf2" {
+    try test__powisf2(0, 0, 1);
+    try test__powihf2(1, 0, 1);
+    try test__powihf2(1.5, 0, 1);
+    try test__powihf2(2, 0, 1);
+    try test__powihf2(math.inf_f16, 0, 1);
+
+    try test__powihf2(-0.0, 0, 1);
+    try test__powihf2(-1, 0, 1);
+    try test__powihf2(-1.5, 0, 1);
+    try test__powihf2(-2, 0, 1);
+    try test__powihf2(-math.inf_f16, 0, 1);
+
+    try test__powihf2(0, 1, 0);
+    try test__powihf2(0, 2, 0);
+    try test__powihf2(0, 3, 0);
+    try test__powihf2(0, 4, 0);
+    try test__powihf2(0, @bitCast(i32, @as(u32, 0x7FFFFFFE)), 0);
+    try test__powihf2(0, @bitCast(i32, @as(u32, 0x7FFFFFFF)), 0);
+
+    try test__powihf2(-0.0, 1, -0.0);
+    try test__powihf2(-0.0, 2, 0);
+    try test__powihf2(-0.0, 3, -0.0);
+    try test__powihf2(-0.0, 4, 0);
+    try test__powihf2(-0.0, @bitCast(i32, @as(u32, 0x7FFFFFFE)), 0);
+    try test__powihf2(-0.0, @bitCast(i32, @as(u32, 0x7FFFFFFF)), -0.0);
+
+    try test__powihf2(1, 1, 1);
+    try test__powihf2(1, 2, 1);
+    try test__powihf2(1, 3, 1);
+    try test__powihf2(1, 4, 1);
+    try test__powihf2(1, @bitCast(i32, @as(u32, 0x7FFFFFFE)), 1);
+    try test__powihf2(1, @bitCast(i32, @as(u32, 0x7FFFFFFF)), 1);
+
+    try test__powihf2(math.inf_f16, 1, math.inf_f16);
+    try test__powihf2(math.inf_f16, 2, math.inf_f16);
+    try test__powihf2(math.inf_f16, 3, math.inf_f16);
+    try test__powihf2(math.inf_f16, 4, math.inf_f16);
+    try test__powihf2(math.inf_f16, @bitCast(i32, @as(u32, 0x7FFFFFFE)), math.inf_f16);
+    try test__powihf2(math.inf_f16, @bitCast(i32, @as(u32, 0x7FFFFFFF)), math.inf_f16);
+
+    try test__powihf2(-math.inf_f16, 1, -math.inf_f16);
+    try test__powihf2(-math.inf_f16, 2, math.inf_f16);
+    try test__powihf2(-math.inf_f16, 3, -math.inf_f16);
+    try test__powihf2(-math.inf_f16, 4, math.inf_f16);
+    try test__powihf2(-math.inf_f16, @bitCast(i32, @as(u32, 0x7FFFFFFE)), math.inf_f16);
+    try test__powihf2(-math.inf_f16, @bitCast(i32, @as(u32, 0x7FFFFFFF)), -math.inf_f16);
+    //
+    try test__powihf2(0, -1, math.inf_f16);
+    try test__powihf2(0, -2, math.inf_f16);
+    try test__powihf2(0, -3, math.inf_f16);
+    try test__powihf2(0, -4, math.inf_f16);
+    try test__powihf2(0, @bitCast(i32, @as(u32, 0x80000002)), math.inf_f16); // 0 ^ anything = +inf
+    try test__powihf2(0, @bitCast(i32, @as(u32, 0x80000001)), math.inf_f16);
+    try test__powihf2(0, @bitCast(i32, @as(u32, 0x80000000)), math.inf_f16);
+
+    try test__powihf2(-0.0, -1, -math.inf_f16);
+    try test__powihf2(-0.0, -2, math.inf_f16);
+    try test__powihf2(-0.0, -3, -math.inf_f16);
+    try test__powihf2(-0.0, -4, math.inf_f16);
+    try test__powihf2(-0.0, @bitCast(i32, @as(u32, 0x80000002)), math.inf_f16); // -0 ^ anything even = +inf
+    try test__powihf2(-0.0, @bitCast(i32, @as(u32, 0x80000001)), -math.inf_f16); // -0 ^ anything odd = -inf
+    try test__powihf2(-0.0, @bitCast(i32, @as(u32, 0x80000000)), math.inf_f16);
+
+    try test__powihf2(1, -1, 1);
+    try test__powihf2(1, -2, 1);
+    try test__powihf2(1, -3, 1);
+    try test__powihf2(1, -4, 1);
+    try test__powihf2(1, @bitCast(i32, @as(u32, 0x80000002)), 1); // 1.0 ^ anything = 1
+    try test__powihf2(1, @bitCast(i32, @as(u32, 0x80000001)), 1);
+    try test__powihf2(1, @bitCast(i32, @as(u32, 0x80000000)), 1);
+
+    try test__powihf2(math.inf_f16, -1, 0);
+    try test__powihf2(math.inf_f16, -2, 0);
+    try test__powihf2(math.inf_f16, -3, 0);
+    try test__powihf2(math.inf_f16, -4, 0);
+    try test__powihf2(math.inf_f16, @bitCast(i32, @as(u32, 0x80000002)), 0);
+    try test__powihf2(math.inf_f16, @bitCast(i32, @as(u32, 0x80000001)), 0);
+    try test__powihf2(math.inf_f16, @bitCast(i32, @as(u32, 0x80000000)), 0);
+    //
+    try test__powihf2(-math.inf_f16, -1, -0.0);
+    try test__powihf2(-math.inf_f16, -2, 0);
+    try test__powihf2(-math.inf_f16, -3, -0.0);
+    try test__powihf2(-math.inf_f16, -4, 0);
+    try test__powihf2(-math.inf_f16, @bitCast(i32, @as(u32, 0x80000002)), 0);
+    try test__powihf2(-math.inf_f16, @bitCast(i32, @as(u32, 0x80000001)), -0.0);
+    try test__powihf2(-math.inf_f16, @bitCast(i32, @as(u32, 0x80000000)), 0);
+
+    try test__powihf2(2, 10, 1024.0);
+    try test__powihf2(-2, 10, 1024.0);
+    try test__powihf2(2, -10, 1.0 / 1024.0);
+    try test__powihf2(-2, -10, 1.0 / 1024.0);
+
+    try test__powihf2(2, 14, 16384.0);
+    try test__powihf2(-2, 14, 16384.0);
+    try test__powihf2(2, 15, 32768.0);
+    try test__powihf2(-2, 15, -32768.0);
+    try test__powihf2(2, 16, math.inf_f16);
+    try test__powihf2(-2, 16, math.inf_f16);
+
+    try test__powihf2(2, -13, 1.0 / 8192.0);
+    try test__powihf2(-2, -13, -1.0 / 8192.0);
+    try test__powihf2(2, -15, 1.0 / 32768.0);
+    try test__powihf2(-2, -15, -1.0 / 32768.0);
+    try test__powihf2(2, -16, 0.0); // expected = 0.0 = 1/(-2**16)
+    try test__powihf2(-2, -16, 0.0); // expected = 0.0 = 1/(2**16)
+}
+
+test "powisf2" {
+    try test__powisf2(0, 0, 1);
+    try test__powisf2(1, 0, 1);
+    try test__powisf2(1.5, 0, 1);
+    try test__powisf2(2, 0, 1);
+    try test__powisf2(math.inf_f32, 0, 1);
+
+    try test__powisf2(-0.0, 0, 1);
+    try test__powisf2(-1, 0, 1);
+    try test__powisf2(-1.5, 0, 1);
+    try test__powisf2(-2, 0, 1);
+    try test__powisf2(-math.inf_f32, 0, 1);
+
+    try test__powisf2(0, 1, 0);
+    try test__powisf2(0, 2, 0);
+    try test__powisf2(0, 3, 0);
+    try test__powisf2(0, 4, 0);
+    try test__powisf2(0, @bitCast(i32, @as(u32, 0x7FFFFFFE)), 0);
+    try test__powisf2(0, @bitCast(i32, @as(u32, 0x7FFFFFFF)), 0);
+
+    try test__powisf2(-0.0, 1, -0.0);
+    try test__powisf2(-0.0, 2, 0);
+    try test__powisf2(-0.0, 3, -0.0);
+    try test__powisf2(-0.0, 4, 0);
+    try test__powisf2(-0.0, @bitCast(i32, @as(u32, 0x7FFFFFFE)), 0);
+    try test__powisf2(-0.0, @bitCast(i32, @as(u32, 0x7FFFFFFF)), -0.0);
+
+    try test__powisf2(1, 1, 1);
+    try test__powisf2(1, 2, 1);
+    try test__powisf2(1, 3, 1);
+    try test__powisf2(1, 4, 1);
+    try test__powisf2(1, @bitCast(i32, @as(u32, 0x7FFFFFFE)), 1);
+    try test__powisf2(1, @bitCast(i32, @as(u32, 0x7FFFFFFF)), 1);
+
+    try test__powisf2(math.inf_f32, 1, math.inf_f32);
+    try test__powisf2(math.inf_f32, 2, math.inf_f32);
+    try test__powisf2(math.inf_f32, 3, math.inf_f32);
+    try test__powisf2(math.inf_f32, 4, math.inf_f32);
+    try test__powisf2(math.inf_f32, @bitCast(i32, @as(u32, 0x7FFFFFFE)), math.inf_f32);
+    try test__powisf2(math.inf_f32, @bitCast(i32, @as(u32, 0x7FFFFFFF)), math.inf_f32);
+
+    try test__powisf2(-math.inf_f32, 1, -math.inf_f32);
+    try test__powisf2(-math.inf_f32, 2, math.inf_f32);
+    try test__powisf2(-math.inf_f32, 3, -math.inf_f32);
+    try test__powisf2(-math.inf_f32, 4, math.inf_f32);
+    try test__powisf2(-math.inf_f32, @bitCast(i32, @as(u32, 0x7FFFFFFE)), math.inf_f32);
+    try test__powisf2(-math.inf_f32, @bitCast(i32, @as(u32, 0x7FFFFFFF)), -math.inf_f32);
+
+    try test__powisf2(0, -1, math.inf_f32);
+    try test__powisf2(0, -2, math.inf_f32);
+    try test__powisf2(0, -3, math.inf_f32);
+    try test__powisf2(0, -4, math.inf_f32);
+    try test__powisf2(0, @bitCast(i32, @as(u32, 0x80000002)), math.inf_f32);
+    try test__powisf2(0, @bitCast(i32, @as(u32, 0x80000001)), math.inf_f32);
+    try test__powisf2(0, @bitCast(i32, @as(u32, 0x80000000)), math.inf_f32);
+
+    try test__powisf2(-0.0, -1, -math.inf_f32);
+    try test__powisf2(-0.0, -2, math.inf_f32);
+    try test__powisf2(-0.0, -3, -math.inf_f32);
+    try test__powisf2(-0.0, -4, math.inf_f32);
+    try test__powisf2(-0.0, @bitCast(i32, @as(u32, 0x80000002)), math.inf_f32);
+    try test__powisf2(-0.0, @bitCast(i32, @as(u32, 0x80000001)), -math.inf_f32);
+    try test__powisf2(-0.0, @bitCast(i32, @as(u32, 0x80000000)), math.inf_f32);
+
+    try test__powisf2(1, -1, 1);
+    try test__powisf2(1, -2, 1);
+    try test__powisf2(1, -3, 1);
+    try test__powisf2(1, -4, 1);
+    try test__powisf2(1, @bitCast(i32, @as(u32, 0x80000002)), 1);
+    try test__powisf2(1, @bitCast(i32, @as(u32, 0x80000001)), 1);
+    try test__powisf2(1, @bitCast(i32, @as(u32, 0x80000000)), 1);
+
+    try test__powisf2(math.inf_f32, -1, 0);
+    try test__powisf2(math.inf_f32, -2, 0);
+    try test__powisf2(math.inf_f32, -3, 0);
+    try test__powisf2(math.inf_f32, -4, 0);
+    try test__powisf2(math.inf_f32, @bitCast(i32, @as(u32, 0x80000002)), 0);
+    try test__powisf2(math.inf_f32, @bitCast(i32, @as(u32, 0x80000001)), 0);
+    try test__powisf2(math.inf_f32, @bitCast(i32, @as(u32, 0x80000000)), 0);
+
+    try test__powisf2(-math.inf_f32, -1, -0.0);
+    try test__powisf2(-math.inf_f32, -2, 0);
+    try test__powisf2(-math.inf_f32, -3, -0.0);
+    try test__powisf2(-math.inf_f32, -4, 0);
+    try test__powisf2(-math.inf_f32, @bitCast(i32, @as(u32, 0x80000002)), 0);
+    try test__powisf2(-math.inf_f32, @bitCast(i32, @as(u32, 0x80000001)), -0.0);
+    try test__powisf2(-math.inf_f32, @bitCast(i32, @as(u32, 0x80000000)), 0);
+
+    try test__powisf2(2.0, 10, 1024.0);
+    try test__powisf2(-2, 10, 1024.0);
+    try test__powisf2(2, -10, 1.0 / 1024.0);
+    try test__powisf2(-2, -10, 1.0 / 1024.0);
+    //
+    try test__powisf2(2, 19, 524288.0);
+    try test__powisf2(-2, 19, -524288.0);
+    try test__powisf2(2, -19, 1.0 / 524288.0);
+    try test__powisf2(-2, -19, -1.0 / 524288.0);
+
+    try test__powisf2(2, 31, 2147483648.0);
+    try test__powisf2(-2, 31, -2147483648.0);
+    try test__powisf2(2, -31, 1.0 / 2147483648.0);
+    try test__powisf2(-2, -31, -1.0 / 2147483648.0);
+}
+
+test "powidf2" {
+    try test__powidf2(0, 0, 1);
+    try test__powidf2(1, 0, 1);
+    try test__powidf2(1.5, 0, 1);
+    try test__powidf2(2, 0, 1);
+    try test__powidf2(math.inf_f64, 0, 1);
+
+    try test__powidf2(-0.0, 0, 1);
+    try test__powidf2(-1, 0, 1);
+    try test__powidf2(-1.5, 0, 1);
+    try test__powidf2(-2, 0, 1);
+    try test__powidf2(-math.inf_f64, 0, 1);
+
+    try test__powidf2(0, 1, 0);
+    try test__powidf2(0, 2, 0);
+    try test__powidf2(0, 3, 0);
+    try test__powidf2(0, 4, 0);
+    try test__powidf2(0, @bitCast(i32, @as(u32, 0x7FFFFFFE)), 0);
+    try test__powidf2(0, @bitCast(i32, @as(u32, 0x7FFFFFFF)), 0);
+
+    try test__powidf2(-0.0, 1, -0.0);
+    try test__powidf2(-0.0, 2, 0);
+    try test__powidf2(-0.0, 3, -0.0);
+    try test__powidf2(-0.0, 4, 0);
+    try test__powidf2(-0.0, @bitCast(i32, @as(u32, 0x7FFFFFFE)), 0);
+    try test__powidf2(-0.0, @bitCast(i32, @as(u32, 0x7FFFFFFF)), -0.0);
+
+    try test__powidf2(1, 1, 1);
+    try test__powidf2(1, 2, 1);
+    try test__powidf2(1, 3, 1);
+    try test__powidf2(1, 4, 1);
+    try test__powidf2(1, @bitCast(i32, @as(u32, 0x7FFFFFFE)), 1);
+    try test__powidf2(1, @bitCast(i32, @as(u32, 0x7FFFFFFF)), 1);
+
+    try test__powidf2(math.inf_f64, 1, math.inf_f64);
+    try test__powidf2(math.inf_f64, 2, math.inf_f64);
+    try test__powidf2(math.inf_f64, 3, math.inf_f64);
+    try test__powidf2(math.inf_f64, 4, math.inf_f64);
+    try test__powidf2(math.inf_f64, @bitCast(i32, @as(u32, 0x7FFFFFFE)), math.inf_f64);
+    try test__powidf2(math.inf_f64, @bitCast(i32, @as(u32, 0x7FFFFFFF)), math.inf_f64);
+
+    try test__powidf2(-math.inf_f64, 1, -math.inf_f64);
+    try test__powidf2(-math.inf_f64, 2, math.inf_f64);
+    try test__powidf2(-math.inf_f64, 3, -math.inf_f64);
+    try test__powidf2(-math.inf_f64, 4, math.inf_f64);
+    try test__powidf2(-math.inf_f64, @bitCast(i32, @as(u32, 0x7FFFFFFE)), math.inf_f64);
+    try test__powidf2(-math.inf_f64, @bitCast(i32, @as(u32, 0x7FFFFFFF)), -math.inf_f64);
+
+    try test__powidf2(0, -1, math.inf_f64);
+    try test__powidf2(0, -2, math.inf_f64);
+    try test__powidf2(0, -3, math.inf_f64);
+    try test__powidf2(0, -4, math.inf_f64);
+    try test__powidf2(0, @bitCast(i32, @as(u32, 0x80000002)), math.inf_f64);
+    try test__powidf2(0, @bitCast(i32, @as(u32, 0x80000001)), math.inf_f64);
+    try test__powidf2(0, @bitCast(i32, @as(u32, 0x80000000)), math.inf_f64);
+
+    try test__powidf2(-0.0, -1, -math.inf_f64);
+    try test__powidf2(-0.0, -2, math.inf_f64);
+    try test__powidf2(-0.0, -3, -math.inf_f64);
+    try test__powidf2(-0.0, -4, math.inf_f64);
+    try test__powidf2(-0.0, @bitCast(i32, @as(u32, 0x80000002)), math.inf_f64);
+    try test__powidf2(-0.0, @bitCast(i32, @as(u32, 0x80000001)), -math.inf_f64);
+    try test__powidf2(-0.0, @bitCast(i32, @as(u32, 0x80000000)), math.inf_f64);
+
+    try test__powidf2(1, -1, 1);
+    try test__powidf2(1, -2, 1);
+    try test__powidf2(1, -3, 1);
+    try test__powidf2(1, -4, 1);
+    try test__powidf2(1, @bitCast(i32, @as(u32, 0x80000002)), 1);
+    try test__powidf2(1, @bitCast(i32, @as(u32, 0x80000001)), 1);
+    try test__powidf2(1, @bitCast(i32, @as(u32, 0x80000000)), 1);
+
+    try test__powidf2(math.inf_f64, -1, 0);
+    try test__powidf2(math.inf_f64, -2, 0);
+    try test__powidf2(math.inf_f64, -3, 0);
+    try test__powidf2(math.inf_f64, -4, 0);
+    try test__powidf2(math.inf_f64, @bitCast(i32, @as(u32, 0x80000002)), 0);
+    try test__powidf2(math.inf_f64, @bitCast(i32, @as(u32, 0x80000001)), 0);
+    try test__powidf2(math.inf_f64, @bitCast(i32, @as(u32, 0x80000000)), 0);
+
+    try test__powidf2(-math.inf_f64, -1, -0.0);
+    try test__powidf2(-math.inf_f64, -2, 0);
+    try test__powidf2(-math.inf_f64, -3, -0.0);
+    try test__powidf2(-math.inf_f64, -4, 0);
+    try test__powidf2(-math.inf_f64, @bitCast(i32, @as(u32, 0x80000002)), 0);
+    try test__powidf2(-math.inf_f64, @bitCast(i32, @as(u32, 0x80000001)), -0.0);
+    try test__powidf2(-math.inf_f64, @bitCast(i32, @as(u32, 0x80000000)), 0);
+
+    try test__powidf2(2, 10, 1024.0);
+    try test__powidf2(-2, 10, 1024.0);
+    try test__powidf2(2, -10, 1.0 / 1024.0);
+    try test__powidf2(-2, -10, 1.0 / 1024.0);
+
+    try test__powidf2(2, 19, 524288.0);
+    try test__powidf2(-2, 19, -524288.0);
+    try test__powidf2(2, -19, 1.0 / 524288.0);
+    try test__powidf2(-2, -19, -1.0 / 524288.0);
+
+    try test__powidf2(2, 31, 2147483648.0);
+    try test__powidf2(-2, 31, -2147483648.0);
+    try test__powidf2(2, -31, 1.0 / 2147483648.0);
+    try test__powidf2(-2, -31, -1.0 / 2147483648.0);
+}
+
+test "powitf2" {
+    try test__powitf2(0, 0, 1);
+    try test__powitf2(1, 0, 1);
+    try test__powitf2(1.5, 0, 1);
+    try test__powitf2(2, 0, 1);
+    try test__powitf2(math.inf_f128, 0, 1);
+
+    try test__powitf2(-0.0, 0, 1);
+    try test__powitf2(-1, 0, 1);
+    try test__powitf2(-1.5, 0, 1);
+    try test__powitf2(-2, 0, 1);
+    try test__powitf2(-math.inf_f128, 0, 1);
+
+    try test__powitf2(0, 1, 0);
+    try test__powitf2(0, 2, 0);
+    try test__powitf2(0, 3, 0);
+    try test__powitf2(0, 4, 0);
+    try test__powitf2(0, @bitCast(i32, @as(u32, 0x7FFFFFFE)), 0);
+    try test__powitf2(0, 0x7FFFFFFF, 0);
+
+    try test__powitf2(-0.0, 1, -0.0);
+    try test__powitf2(-0.0, 2, 0);
+    try test__powitf2(-0.0, 3, -0.0);
+    try test__powitf2(-0.0, 4, 0);
+    try test__powitf2(-0.0, @bitCast(i32, @as(u32, 0x7FFFFFFE)), 0);
+    try test__powitf2(-0.0, @bitCast(i32, @as(u32, 0x7FFFFFFF)), -0.0);
+
+    try test__powitf2(1, 1, 1);
+    try test__powitf2(1, 2, 1);
+    try test__powitf2(1, 3, 1);
+    try test__powitf2(1, 4, 1);
+    try test__powitf2(1, @bitCast(i32, @as(u32, 0x7FFFFFFE)), 1);
+    try test__powitf2(1, @bitCast(i32, @as(u32, 0x7FFFFFFF)), 1);
+
+    try test__powitf2(math.inf_f128, 1, math.inf_f128);
+    try test__powitf2(math.inf_f128, 2, math.inf_f128);
+    try test__powitf2(math.inf_f128, 3, math.inf_f128);
+    try test__powitf2(math.inf_f128, 4, math.inf_f128);
+    try test__powitf2(math.inf_f128, @bitCast(i32, @as(u32, 0x7FFFFFFE)), math.inf_f128);
+    try test__powitf2(math.inf_f128, @bitCast(i32, @as(u32, 0x7FFFFFFF)), math.inf_f128);
+
+    try test__powitf2(-math.inf_f128, 1, -math.inf_f128);
+    try test__powitf2(-math.inf_f128, 2, math.inf_f128);
+    try test__powitf2(-math.inf_f128, 3, -math.inf_f128);
+    try test__powitf2(-math.inf_f128, 4, math.inf_f128);
+    try test__powitf2(-math.inf_f128, @bitCast(i32, @as(u32, 0x7FFFFFFE)), math.inf_f128);
+    try test__powitf2(-math.inf_f128, @bitCast(i32, @as(u32, 0x7FFFFFFF)), -math.inf_f128);
+
+    try test__powitf2(0, -1, math.inf_f128);
+    try test__powitf2(0, -2, math.inf_f128);
+    try test__powitf2(0, -3, math.inf_f128);
+    try test__powitf2(0, -4, math.inf_f128);
+    try test__powitf2(0, @bitCast(i32, @as(u32, 0x80000002)), math.inf_f128);
+    try test__powitf2(0, @bitCast(i32, @as(u32, 0x80000001)), math.inf_f128);
+    try test__powitf2(0, @bitCast(i32, @as(u32, 0x80000000)), math.inf_f128);
+
+    try test__powitf2(-0.0, -1, -math.inf_f128);
+    try test__powitf2(-0.0, -2, math.inf_f128);
+    try test__powitf2(-0.0, -3, -math.inf_f128);
+    try test__powitf2(-0.0, -4, math.inf_f128);
+    try test__powitf2(-0.0, @bitCast(i32, @as(u32, 0x80000002)), math.inf_f128);
+    try test__powitf2(-0.0, @bitCast(i32, @as(u32, 0x80000001)), -math.inf_f128);
+    try test__powitf2(-0.0, @bitCast(i32, @as(u32, 0x80000000)), math.inf_f128);
+
+    try test__powitf2(1, -1, 1);
+    try test__powitf2(1, -2, 1);
+    try test__powitf2(1, -3, 1);
+    try test__powitf2(1, -4, 1);
+    try test__powitf2(1, @bitCast(i32, @as(u32, 0x80000002)), 1);
+    try test__powitf2(1, @bitCast(i32, @as(u32, 0x80000001)), 1);
+    try test__powitf2(1, @bitCast(i32, @as(u32, 0x80000000)), 1);
+
+    try test__powitf2(math.inf_f128, -1, 0);
+    try test__powitf2(math.inf_f128, -2, 0);
+    try test__powitf2(math.inf_f128, -3, 0);
+    try test__powitf2(math.inf_f128, -4, 0);
+    try test__powitf2(math.inf_f128, @bitCast(i32, @as(u32, 0x80000002)), 0);
+    try test__powitf2(math.inf_f128, @bitCast(i32, @as(u32, 0x80000001)), 0);
+    try test__powitf2(math.inf_f128, @bitCast(i32, @as(u32, 0x80000000)), 0);
+
+    try test__powitf2(-math.inf_f128, -1, -0.0);
+    try test__powitf2(-math.inf_f128, -2, 0);
+    try test__powitf2(-math.inf_f128, -3, -0.0);
+    try test__powitf2(-math.inf_f128, -4, 0);
+    try test__powitf2(-math.inf_f128, @bitCast(i32, @as(u32, 0x80000002)), 0);
+    try test__powitf2(-math.inf_f128, @bitCast(i32, @as(u32, 0x80000001)), -0.0);
+    try test__powitf2(-math.inf_f128, @bitCast(i32, @as(u32, 0x80000000)), 0);
+
+    try test__powitf2(2, 10, 1024.0);
+    try test__powitf2(-2, 10, 1024.0);
+    try test__powitf2(2, -10, 1.0 / 1024.0);
+    try test__powitf2(-2, -10, 1.0 / 1024.0);
+
+    try test__powitf2(2, 19, 524288.0);
+    try test__powitf2(-2, 19, -524288.0);
+    try test__powitf2(2, -19, 1.0 / 524288.0);
+    try test__powitf2(-2, -19, -1.0 / 524288.0);
+
+    try test__powitf2(2, 31, 2147483648.0);
+    try test__powitf2(-2, 31, -2147483648.0);
+    try test__powitf2(2, -31, 1.0 / 2147483648.0);
+    try test__powitf2(-2, -31, -1.0 / 2147483648.0);
+}
+
+test "powixf2" {
+    try test__powixf2(0, 0, 1);
+    try test__powixf2(1, 0, 1);
+    try test__powixf2(1.5, 0, 1);
+    try test__powixf2(2, 0, 1);
+    try test__powixf2(math.inf_f80, 0, 1);
+
+    try test__powixf2(-0.0, 0, 1);
+    try test__powixf2(-1, 0, 1);
+    try test__powixf2(-1.5, 0, 1);
+    try test__powixf2(-2, 0, 1);
+    try test__powixf2(-math.inf_f80, 0, 1);
+
+    try test__powixf2(0, 1, 0);
+    try test__powixf2(0, 2, 0);
+    try test__powixf2(0, 3, 0);
+    try test__powixf2(0, 4, 0);
+    try test__powixf2(0, @bitCast(i32, @as(u32, 0x7FFFFFFE)), 0);
+    try test__powixf2(0, @bitCast(i32, @as(u32, 0x7FFFFFFF)), 0);
+
+    try test__powixf2(-0.0, 1, -0.0);
+    try test__powixf2(-0.0, 2, 0);
+    try test__powixf2(-0.0, 3, -0.0);
+    try test__powixf2(-0.0, 4, 0);
+    try test__powixf2(-0.0, @bitCast(i32, @as(u32, 0x7FFFFFFE)), 0);
+    try test__powixf2(-0.0, @bitCast(i32, @as(u32, 0x7FFFFFFF)), -0.0);
+
+    try test__powixf2(1, 1, 1);
+    try test__powixf2(1, 2, 1);
+    try test__powixf2(1, 3, 1);
+    try test__powixf2(1, 4, 1);
+    try test__powixf2(1, @bitCast(i32, @as(u32, 0x7FFFFFFE)), 1);
+    try test__powixf2(1, @bitCast(i32, @as(u32, 0x7FFFFFFF)), 1);
+
+    try test__powixf2(math.inf_f80, 1, math.inf_f80);
+    try test__powixf2(math.inf_f80, 2, math.inf_f80);
+    try test__powixf2(math.inf_f80, 3, math.inf_f80);
+    try test__powixf2(math.inf_f80, 4, math.inf_f80);
+    try test__powixf2(math.inf_f80, @bitCast(i32, @as(u32, 0x7FFFFFFE)), math.inf_f80);
+    try test__powixf2(math.inf_f80, @bitCast(i32, @as(u32, 0x7FFFFFFF)), math.inf_f80);
+
+    try test__powixf2(-math.inf_f80, 1, -math.inf_f80);
+    try test__powixf2(-math.inf_f80, 2, math.inf_f80);
+    try test__powixf2(-math.inf_f80, 3, -math.inf_f80);
+    try test__powixf2(-math.inf_f80, 4, math.inf_f80);
+    try test__powixf2(-math.inf_f80, @bitCast(i32, @as(u32, 0x7FFFFFFE)), math.inf_f80);
+    try test__powixf2(-math.inf_f80, @bitCast(i32, @as(u32, 0x7FFFFFFF)), -math.inf_f80);
+
+    try test__powixf2(0, -1, math.inf_f80);
+    try test__powixf2(0, -2, math.inf_f80);
+    try test__powixf2(0, -3, math.inf_f80);
+    try test__powixf2(0, -4, math.inf_f80);
+    try test__powixf2(0, @bitCast(i32, @as(u32, 0x80000002)), math.inf_f80);
+    try test__powixf2(0, @bitCast(i32, @as(u32, 0x80000001)), math.inf_f80);
+    try test__powixf2(0, @bitCast(i32, @as(u32, 0x80000000)), math.inf_f80);
+
+    try test__powixf2(-0.0, -1, -math.inf_f80);
+    try test__powixf2(-0.0, -2, math.inf_f80);
+    try test__powixf2(-0.0, -3, -math.inf_f80);
+    try test__powixf2(-0.0, -4, math.inf_f80);
+    try test__powixf2(-0.0, @bitCast(i32, @as(u32, 0x80000002)), math.inf_f80);
+    try test__powixf2(-0.0, @bitCast(i32, @as(u32, 0x80000001)), -math.inf_f80);
+    try test__powixf2(-0.0, @bitCast(i32, @as(u32, 0x80000000)), math.inf_f80);
+
+    try test__powixf2(1, -1, 1);
+    try test__powixf2(1, -2, 1);
+    try test__powixf2(1, -3, 1);
+    try test__powixf2(1, -4, 1);
+    try test__powixf2(1, @bitCast(i32, @as(u32, 0x80000002)), 1);
+    try test__powixf2(1, @bitCast(i32, @as(u32, 0x80000001)), 1);
+    try test__powixf2(1, @bitCast(i32, @as(u32, 0x80000000)), 1);
+
+    try test__powixf2(math.inf_f80, -1, 0);
+    try test__powixf2(math.inf_f80, -2, 0);
+    try test__powixf2(math.inf_f80, -3, 0);
+    try test__powixf2(math.inf_f80, -4, 0);
+    try test__powixf2(math.inf_f80, @bitCast(i32, @as(u32, 0x80000002)), 0);
+    try test__powixf2(math.inf_f80, @bitCast(i32, @as(u32, 0x80000001)), 0);
+    try test__powixf2(math.inf_f80, @bitCast(i32, @as(u32, 0x80000000)), 0);
+
+    try test__powixf2(-math.inf_f80, -1, -0.0);
+    try test__powixf2(-math.inf_f80, -2, 0);
+    try test__powixf2(-math.inf_f80, -3, -0.0);
+    try test__powixf2(-math.inf_f80, -4, 0);
+    try test__powixf2(-math.inf_f80, @bitCast(i32, @as(u32, 0x80000002)), 0);
+    try test__powixf2(-math.inf_f80, @bitCast(i32, @as(u32, 0x80000001)), -0.0);
+    try test__powixf2(-math.inf_f80, @bitCast(i32, @as(u32, 0x80000000)), 0);
+
+    try test__powixf2(2, 10, 1024.0);
+    try test__powixf2(-2, 10, 1024.0);
+    try test__powixf2(2, -10, 1.0 / 1024.0);
+    try test__powixf2(-2, -10, 1.0 / 1024.0);
+
+    try test__powixf2(2, 19, 524288.0);
+    try test__powixf2(-2, 19, -524288.0);
+    try test__powixf2(2, -19, 1.0 / 524288.0);
+    try test__powixf2(-2, -19, -1.0 / 524288.0);
+
+    try test__powixf2(2, 31, 2147483648.0);
+    try test__powixf2(-2, 31, -2147483648.0);
+    try test__powixf2(2, -31, 1.0 / 2147483648.0);
+    try test__powixf2(-2, -31, -1.0 / 2147483648.0);
+}
lib/compiler_rt/README.md
@@ -328,11 +328,11 @@ Integer and Float Operations
 | ✓ | __negtf2           | f128 | ∅    | f128 | ..                             |
 | ✓ | __negxf2           | f80  | ∅    | f80  | ..                             |
 |   |                    |      |      |      | **Floating point raised to integer power** |
-| ✗ | __powihf2          | f16  | f16  | f16  | `a ^ b`                        |
-| ✗ | __powisf2          | f32  | f32  | f32  | ..                             |
-| ✗ | __powidf2          | f64  | f64  | f64  | ..                             |
-| ✗ | __powitf2          | f128 | f128 | f128 | ..                             |
-| ✗ | __powixf2          | f80  | f80  | f80  | ..                             |
+| ✓ | __powihf2          | f16  | i32  | f16  | `a ^ b`                        |
+| ✓ | __powisf2          | f32  | i32  | f32  | ..                             |
+| ✓ | __powidf2          | f64  | i32  | f64  | ..                             |
+| ✓ | __powitf2          | f128 | i32  | f128 | ..                             |
+| ✓ | __powixf2          | f80  | i32  | f80  | ..                             |
 | ✓ | __mulhc3           | all4 | f16  | f16  | `(a+ib) * (c+id)`              |
 | ✓ | __mulsc3           | all4 | f32  | f32  | ..                             |
 | ✓ | __muldc3           | all4 | f64  | f64  | ..                             |
lib/compiler_rt.zig
@@ -23,6 +23,7 @@ comptime {
     _ = @import("compiler_rt/multf3.zig");
     _ = @import("compiler_rt/mulxf3.zig");
 
+    _ = @import("compiler_rt/powiXf2.zig");
     _ = @import("compiler_rt/mulc3.zig");
     _ = @import("compiler_rt/mulhc3.zig");
     _ = @import("compiler_rt/mulsc3.zig");
tools/gen_stubs.zig
@@ -833,6 +833,11 @@ const blacklisted_symbols = [_][]const u8{
     "__popcountdi2",
     "__popcountsi2",
     "__popcountti2",
+    "__powidf2",
+    "__powihf2",
+    "__powisf2",
+    "__powitf2",
+    "__powixf2",
     "__roundh",
     "__roundx",
     "__sincosh",