authorgravatar for kiyonnxperiaz@gmail.comTemariVirus <kiyonnxperiaz@gmail.com> 2025-12-13 04:23:57+08:00
committergravatar for kiyonnxperiaz@gmail.comTemariVirus <kiyonnxperiaz@gmail.com> 2026-03-16 15:32:09+08:00
log06d9ab7121c30e4142e48908ed8ef79c3387ad30
treec246abe683a0bc28c1bcc8bccc9e39132ff98cee
parentabd099e97ff45395ec6780a88910da4d915f82c9
signaturebadge-check Signed by SSH key SHA256:+zAK94uwewsXTNmaLt3PC6gO2ZcmUQey3+5ib4pNN3k

std.math.pow: fix wrong answer for large even exponents


1 files changed, 7 insertions(+), 1 deletions(-)

lib/std/math/pow.zig+7-1
...@@ -124,7 +124,9 @@ pub fn pow(comptime T: type, x: T, y: T) T {...@@ -124,7 +124,9 @@ pub fn pow(comptime T: type, x: T, y: T) T {
124 return math.nan(T);124 return math.nan(T);
125 }125 }
126 if (yi >= 1 << (@typeInfo(T).float.bits - 1)) {126 if (yi >= 1 << (@typeInfo(T).float.bits - 1)) {
127 return @exp(y * @log(x));127 // yi is a large even int, so the result is always positive
128 // and the sign of x doesn't matter
129 return @exp(y * @log(@abs(x)));
128 }130 }
129131
130 // a = a1 * 2^ae132 // a = a1 * 2^ae
...@@ -208,6 +210,7 @@ test pow {...@@ -208,6 +210,7 @@ test pow {
208 try expect(math.approxEqAbs(f32, pow(f32, 1.5, 3.3), 3.811546, epsilon));210 try expect(math.approxEqAbs(f32, pow(f32, 1.5, 3.3), 3.811546, epsilon));
209 try expect(math.approxEqAbs(f32, pow(f32, 37.45, 3.3), 155736.703125, epsilon));211 try expect(math.approxEqAbs(f32, pow(f32, 37.45, 3.3), 155736.703125, epsilon));
210 try expect(math.approxEqAbs(f32, pow(f32, 89.123, 3.3), 2722489.5, epsilon));212 try expect(math.approxEqAbs(f32, pow(f32, 89.123, 3.3), 2722489.5, epsilon));
213 try expect(math.approxEqAbs(f32, pow(f32, -1.0, 1e10), 1.0, epsilon));
211214
212 try expect(math.approxEqAbs(f64, pow(f64, 0.0, 3.3), 0.0, epsilon));215 try expect(math.approxEqAbs(f64, pow(f64, 0.0, 3.3), 0.0, epsilon));
213 try expect(math.approxEqAbs(f64, pow(f64, 0.8923, 3.3), 0.686572, epsilon));216 try expect(math.approxEqAbs(f64, pow(f64, 0.8923, 3.3), 0.686572, epsilon));
...@@ -215,6 +218,7 @@ test pow {...@@ -215,6 +218,7 @@ test pow {
215 try expect(math.approxEqAbs(f64, pow(f64, 1.5, 3.3), 3.811546, epsilon));218 try expect(math.approxEqAbs(f64, pow(f64, 1.5, 3.3), 3.811546, epsilon));
216 try expect(math.approxEqAbs(f64, pow(f64, 37.45, 3.3), 155736.7160616, epsilon));219 try expect(math.approxEqAbs(f64, pow(f64, 37.45, 3.3), 155736.7160616, epsilon));
217 try expect(math.approxEqAbs(f64, pow(f64, 89.123, 3.3), 2722490.231436, epsilon));220 try expect(math.approxEqAbs(f64, pow(f64, 89.123, 3.3), 2722490.231436, epsilon));
221 try expect(math.approxEqAbs(f64, pow(f64, -1.0, 1e20), 1.0, epsilon));
218}222}
219223
220test "special" {224test "special" {
...@@ -265,4 +269,6 @@ test "overflow" {...@@ -265,4 +269,6 @@ test "overflow" {
265 try expect(math.isNegativeInf(pow(f64, -2, (1 << 32) + 1)));269 try expect(math.isNegativeInf(pow(f64, -2, (1 << 32) + 1)));
266 try expect(pow(f64, 0.5, 1 << 45) == 0);270 try expect(pow(f64, 0.5, 1 << 45) == 0);
267 try expect(math.isPositiveInf(pow(f64, 0.5, -(1 << 45))));271 try expect(math.isPositiveInf(pow(f64, 0.5, -(1 << 45))));
272 try expect(math.isPositiveInf(pow(f64, -2, 1 << 64)));
273 try expect(pow(f64, 0.5, 1 << 64) == 0);
268}274}