| ... | @@ -178,10 +178,26 @@ pub fn pow(comptime T: type, x: T, y: T) T { | ... | @@ -178,10 +178,26 @@ pub fn pow(comptime T: type, x: T, y: T) T { |
| 178 | } | 178 | } |
| 179 | | 179 | |
| 180 | fn isOddInteger(x: f64) bool { | 180 | fn isOddInteger(x: f64) bool { |
| | 181 | if (@abs(x) >= 1 << 53) { |
| | 182 | // From https://golang.org/src/math/pow.go |
| | 183 | // 1 << 53 is the largest exact integer in the float64 format. |
| | 184 | // Any number outside this range will be truncated before the decimal point and therefore will always be |
| | 185 | // an even integer. |
| | 186 | // Without this check and if x overflows i64 the @intFromFloat(r.ipart) conversion below will panic |
| | 187 | return false; |
| | 188 | } |
| 181 | const r = math.modf(x); | 189 | const r = math.modf(x); |
| 182 | return r.fpart == 0.0 and @as(i64, @intFromFloat(r.ipart)) & 1 == 1; | 190 | return r.fpart == 0.0 and @as(i64, @intFromFloat(r.ipart)) & 1 == 1; |
| 183 | } | 191 | } |
| 184 | | 192 | |
| | 193 | test "math.pow.isOddInteger" { |
| | 194 | try expect(isOddInteger(math.maxInt(i64) * 2) == false); |
| | 195 | try expect(isOddInteger(math.maxInt(i64) * 2 + 1) == false); |
| | 196 | try expect(isOddInteger(1 << 53) == false); |
| | 197 | try expect(isOddInteger(12.0) == false); |
| | 198 | try expect(isOddInteger(15.0) == true); |
| | 199 | } |
| | 200 | |
| 185 | test "math.pow" { | 201 | test "math.pow" { |
| 186 | const epsilon = 0.000001; | 202 | const epsilon = 0.000001; |
| 187 | | 203 | |