Skip to content

Commit a78ab81

Browse files
bors[bot]domnacuviper
authored
Merge #116
116: Fixes nan value for powc of zero r=cuviper a=domna Fixes #114 `@cuviper` I just added a check for zero here as I suggested in #114. Co-authored-by: domna <florian.dobener@physik.hu-berlin.de> Co-authored-by: Florian Dobener <github@schroedingerscat.org> Co-authored-by: Josh Stone <cuviper@gmail.com>
2 parents 23ccbd9 + 6a593c6 commit a78ab81

File tree

4 files changed

+48
-17
lines changed

4 files changed

+48
-17
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ categories = ["algorithms", "data-structures", "science", "no-std"]
88
license = "MIT OR Apache-2.0"
99
name = "num-complex"
1010
repository = "https://github.com/rust-num/num-complex"
11-
version = "0.4.3"
11+
version = "0.4.4"
1212
readme = "README.md"
1313
exclude = ["/bors.toml", "/ci/*", "/.github/*"]
1414
edition = "2018"

RELEASES.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,19 @@
1+
# Release 0.4.4 (2023-08-13)
2+
3+
- [Fixes NaN value for `powc` of zero][116]
4+
5+
**Contributors**: @cuviper, @domna
6+
7+
[116]: https://github.com/rust-num/num-complex/pull/116
8+
19
# Release 0.4.3 (2023-01-19)
210

311
- [`Complex` now optionally supports `bytecheck` 0.6 and `rkyv` 0.7][110].
412

513
**Contributors**: @cuviper, @zyansheep
614

15+
[110]: https://github.com/rust-num/num-complex/pull/110
16+
717
# Release 0.4.2 (2022-06-17)
818

919
- [The new `ComplexFloat` trait][95] provides a generic abstraction between

ci/test_full.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ cargo generate-lockfile
3838
# libm 0.2.6 started using {float}::EPSILON
3939
check_version 1.43 || cargo update -p libm --precise 0.2.5
4040

41+
# Some crates moved to Rust 1.56 / 2021
42+
check_version 1.56 || (
43+
cargo update -p quote --precise 1.0.30
44+
cargo update -p proc-macro2 --precise 1.0.65
45+
cargo update -p rkyv --precise 0.7.40
46+
cargo update -p bytecheck --precise 0.6.9
47+
)
48+
4149
set -x
4250

4351
# test the default

src/lib.rs

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,9 @@ impl<T: Float> Complex<T> {
342342
/// Raises `self` to a floating point power.
343343
#[inline]
344344
pub fn powf(self, exp: T) -> Self {
345+
if exp.is_zero() {
346+
return Self::one();
347+
}
345348
// formula: x^y = (ρ e^(i θ))^y = ρ^y e^(i θ y)
346349
// = from_polar(ρ^y, θ y)
347350
let (r, theta) = self.to_polar();
@@ -361,22 +364,11 @@ impl<T: Float> Complex<T> {
361364
/// Raises `self` to a complex power.
362365
#[inline]
363366
pub fn powc(self, exp: Self) -> Self {
364-
// formula: x^y = (a + i b)^(c + i d)
365-
// = (ρ e^(i θ))^c (ρ e^(i θ))^(i d)
366-
// where ρ=|x| and θ=arg(x)
367-
// = ρ^c e^(−d θ) e^(i c θ) ρ^(i d)
368-
// = p^c e^(−d θ) (cos(c θ)
369-
// + i sin(c θ)) (cos(d ln(ρ)) + i sin(d ln(ρ)))
370-
// = p^c e^(−d θ) (
371-
// cos(c θ) cos(d ln(ρ)) − sin(c θ) sin(d ln(ρ))
372-
// + i(cos(c θ) sin(d ln(ρ)) + sin(c θ) cos(d ln(ρ))))
373-
// = p^c e^(−d θ) (cos(c θ + d ln(ρ)) + i sin(c θ + d ln(ρ)))
374-
// = from_polar(p^c e^(−d θ), c θ + d ln(ρ))
375-
let (r, theta) = self.to_polar();
376-
Self::from_polar(
377-
r.powf(exp.re) * (-exp.im * theta).exp(),
378-
exp.re * theta + exp.im * r.ln(),
379-
)
367+
if exp.is_zero() {
368+
return Self::one();
369+
}
370+
// formula: x^y = exp(y * ln(x))
371+
(exp * self.ln()).exp()
380372
}
381373

382374
/// Raises a floating point number to the complex power `self`.
@@ -1715,6 +1707,9 @@ pub(crate) mod test {
17151707

17161708
#[cfg(any(feature = "std", feature = "libm"))]
17171709
pub(crate) mod float {
1710+
1711+
use core::f64::INFINITY;
1712+
17181713
use super::*;
17191714
use num_traits::{Float, Pow};
17201715

@@ -1908,6 +1903,19 @@ pub(crate) mod test {
19081903
Complex::new(1.65826, -0.33502),
19091904
1e-5
19101905
));
1906+
let z = Complex::new(0.0, 0.0);
1907+
assert!(close(z.powc(b), z));
1908+
assert!(z.powc(Complex64::new(0., INFINITY)).is_nan());
1909+
assert!(z.powc(Complex64::new(10., INFINITY)).is_nan());
1910+
assert!(z.powc(Complex64::new(INFINITY, INFINITY)).is_nan());
1911+
assert!(close(z.powc(Complex64::new(INFINITY, 0.)), z));
1912+
assert!(z.powc(Complex64::new(-1., 0.)).re.is_infinite());
1913+
assert!(z.powc(Complex64::new(-1., 0.)).im.is_nan());
1914+
1915+
for c in all_consts.iter() {
1916+
assert_eq!(c.powc(_0_0i), _1_0i);
1917+
}
1918+
assert_eq!(_nan_nani.powc(_0_0i), _1_0i);
19111919
}
19121920

19131921
#[test]
@@ -1917,6 +1925,11 @@ pub(crate) mod test {
19171925
assert!(close_to_tol(c.powf(3.5), expected, 1e-5));
19181926
assert!(close_to_tol(Pow::pow(c, 3.5_f64), expected, 1e-5));
19191927
assert!(close_to_tol(Pow::pow(c, 3.5_f32), expected, 1e-5));
1928+
1929+
for c in all_consts.iter() {
1930+
assert_eq!(c.powf(0.0), _1_0i);
1931+
}
1932+
assert_eq!(_nan_nani.powf(0.0), _1_0i);
19201933
}
19211934

19221935
#[test]

0 commit comments

Comments
 (0)