| ... | @@ -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 | } |
| 129 | | 131 | |
| 130 | // a = a1 * 2^ae | 132 | // 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)); |
| 211 | | 214 | |
| 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 | } |
| 219 | | 223 | |
| 220 | test "special" { | 224 | test "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 | } |