1//! a raised to integer power of b
2//! ported from https://github.com/llvm-mirror/compiler-rt/blob/release_80/lib/builtins/powisf2.c
3//! Multiplication order (left-to-right or right-to-left) does not matter for
4//! error propagation and this method is optimized for performance, not accuracy.
5
6const compiler_rt = @import("../compiler_rt.zig");
7const symbol = compiler_rt.symbol;
8
9comptime {
10 symbol(&__powihf2, "__powihf2");
11 symbol(&__powisf2, "__powisf2");
12 symbol(&__powidf2, "__powidf2");
13 symbol(&__powixf2, "__powixf2");
14 if (compiler_rt.want_ppc_abi) {
15 symbol(&__powitf2, "__powikf2");
16 } else {
17 symbol(&__powitf2, "__powitf2");
18 }
19}
20
21inline fn powiXf2(comptime FT: type, a: FT, b: i32) FT {
22 var x_a: FT = a;
23 var x_b: i32 = b;
24 const is_recip: bool = b < 0;
25 var r: FT = 1.0;
26 while (true) {
27 if (@as(u32, @bitCast(x_b)) & @as(u32, 1) != 0) {
28 r *= x_a;
29 }
30 x_b = @divTrunc(x_b, @as(i32, 2));
31 if (x_b == 0) break;
32 x_a *= x_a; // Multiplication of x_a propagates the error
33 }
34 return if (is_recip) 1 / r else r;
35}
36
37fn __powihf2(a: compiler_rt.f16.Abi, b: i32) callconv(.c) compiler_rt.f16.Abi {
38 return compiler_rt.f16.toAbi(powi_f16(compiler_rt.f16.fromAbi(a), b));
39}
40pub fn powi_f16(a: f16, b: i32) f16 {
41 return powiXf2(f16, a, b);
42}
43
44fn __powisf2(a: compiler_rt.f32.Abi, b: i32) callconv(.c) compiler_rt.f32.Abi {
45 return compiler_rt.f32.toAbi(powi_f32(compiler_rt.f32.fromAbi(a), b));
46}
47pub fn powi_f32(a: f32, b: i32) f32 {
48 return powiXf2(f32, a, b);
49}
50
51fn __powidf2(a: compiler_rt.f64.Abi, b: i32) callconv(.c) compiler_rt.f64.Abi {
52 return compiler_rt.f64.toAbi(powi_f64(compiler_rt.f64.fromAbi(a), b));
53}
54pub fn powi_f64(a: f64, b: i32) f64 {
55 return powiXf2(f64, a, b);
56}
57
58fn __powixf2(a: compiler_rt.f80.Abi, b: i32) callconv(.c) compiler_rt.f80.Abi {
59 return compiler_rt.f80.toAbi(powi_f80(compiler_rt.f80.fromAbi(a), b));
60}
61pub fn powi_f80(a: f80, b: i32) f80 {
62 return powiXf2(f80, a, b);
63}
64
65fn __powitf2(a: compiler_rt.f128.Abi, b: i32) callconv(.c) compiler_rt.f128.Abi {
66 return compiler_rt.f128.toAbi(powi_f128(compiler_rt.f128.fromAbi(a), b));
67}
68pub fn powi_f128(a: f128, b: i32) f128 {
69 return powiXf2(f128, a, b);
70}
71
72test {
73 _ = @import("powiXf2_test.zig");
74}