|
1 | 1 | use num_bigint::{BigInt, ToBigInt};
|
| 2 | +use num_complex::Complex64; |
2 | 3 | use num_rational::Ratio;
|
3 | 4 | use num_traits::{pow, ToPrimitive, Zero};
|
4 | 5 |
|
@@ -134,12 +135,16 @@ fn inner_divmod(v1: f64, v2: f64, vm: &VirtualMachine) -> PyResult<(f64, f64)> {
|
134 | 135 | }
|
135 | 136 | }
|
136 | 137 |
|
137 |
| -pub fn float_pow(v1: f64, v2: f64, vm: &VirtualMachine) -> PyResult<f64> { |
| 138 | +pub fn float_pow(v1: f64, v2: f64, vm: &VirtualMachine) -> PyResult { |
138 | 139 | if v1.is_zero() {
|
139 | 140 | let msg = format!("{} cannot be raised to a negative power", v1);
|
140 | 141 | Err(vm.new_zero_division_error(msg))
|
| 142 | + } else if v1.is_sign_negative() && (v2.floor() - v2).abs() > f64::EPSILON { |
| 143 | + let v1 = Complex64::new(v1, 0.); |
| 144 | + let v2 = Complex64::new(v2, 0.); |
| 145 | + v1.powc(v2).into_pyobject(vm) |
141 | 146 | } else {
|
142 |
| - Ok(v1.powf(v2)) |
| 147 | + v1.powf(v2).into_pyobject(vm) |
143 | 148 | }
|
144 | 149 | }
|
145 | 150 |
|
@@ -258,6 +263,17 @@ impl PyFloat {
|
258 | 263 | )
|
259 | 264 | }
|
260 | 265 |
|
| 266 | + #[inline] |
| 267 | + fn complex_op<F>(&self, other: PyObjectRef, op: F, vm: &VirtualMachine) -> PyResult |
| 268 | + where |
| 269 | + F: Fn(f64, f64) -> PyResult, |
| 270 | + { |
| 271 | + try_float(&other, vm)?.map_or_else( |
| 272 | + || Ok(vm.ctx.not_implemented()), |
| 273 | + |other| op(self.value, other).into_pyobject(vm), |
| 274 | + ) |
| 275 | + } |
| 276 | + |
261 | 277 | #[inline]
|
262 | 278 | fn tuple_op<F>(&self, other: PyObjectRef, op: F, vm: &VirtualMachine) -> PyResult
|
263 | 279 | where
|
@@ -331,12 +347,12 @@ impl PyFloat {
|
331 | 347 |
|
332 | 348 | #[pymethod(name = "__pow__")]
|
333 | 349 | fn pow(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
334 |
| - self.simple_op(other, |a, b| float_pow(a, b, vm), vm) |
| 350 | + self.complex_op(other, |a, b| float_pow(a, b, vm), vm) |
335 | 351 | }
|
336 | 352 |
|
337 | 353 | #[pymethod(name = "__rpow__")]
|
338 | 354 | fn rpow(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult {
|
339 |
| - self.simple_op(other, |a, b| float_pow(b, a, vm), vm) |
| 355 | + self.complex_op(other, |a, b| float_pow(b, a, vm), vm) |
340 | 356 | }
|
341 | 357 |
|
342 | 358 | #[pymethod(name = "__sub__")]
|
|
0 commit comments