Skip to content

Commit

Permalink
Merge #116
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
4 people authored Aug 13, 2023
2 parents 23ccbd9 + 6a593c6 commit a78ab81
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 17 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ categories = ["algorithms", "data-structures", "science", "no-std"]
license = "MIT OR Apache-2.0"
name = "num-complex"
repository = "https://github.com/rust-num/num-complex"
version = "0.4.3"
version = "0.4.4"
readme = "README.md"
exclude = ["/bors.toml", "/ci/*", "/.github/*"]
edition = "2018"
Expand Down
10 changes: 10 additions & 0 deletions RELEASES.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
# Release 0.4.4 (2023-08-13)

- [Fixes NaN value for `powc` of zero][116]

**Contributors**: @cuviper, @domna

[116]: https://github.com/rust-num/num-complex/pull/116

# Release 0.4.3 (2023-01-19)

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

**Contributors**: @cuviper, @zyansheep

[110]: https://github.com/rust-num/num-complex/pull/110

# Release 0.4.2 (2022-06-17)

- [The new `ComplexFloat` trait][95] provides a generic abstraction between
Expand Down
8 changes: 8 additions & 0 deletions ci/test_full.sh
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,14 @@ cargo generate-lockfile
# libm 0.2.6 started using {float}::EPSILON
check_version 1.43 || cargo update -p libm --precise 0.2.5

# Some crates moved to Rust 1.56 / 2021
check_version 1.56 || (
cargo update -p quote --precise 1.0.30
cargo update -p proc-macro2 --precise 1.0.65
cargo update -p rkyv --precise 0.7.40
cargo update -p bytecheck --precise 0.6.9
)

set -x

# test the default
Expand Down
45 changes: 29 additions & 16 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,9 @@ impl<T: Float> Complex<T> {
/// Raises `self` to a floating point power.
#[inline]
pub fn powf(self, exp: T) -> Self {
if exp.is_zero() {
return Self::one();
}
// formula: x^y = (ρ e^(i θ))^y = ρ^y e^(i θ y)
// = from_polar(ρ^y, θ y)
let (r, theta) = self.to_polar();
Expand All @@ -361,22 +364,11 @@ impl<T: Float> Complex<T> {
/// Raises `self` to a complex power.
#[inline]
pub fn powc(self, exp: Self) -> Self {
// formula: x^y = (a + i b)^(c + i d)
// = (ρ e^(i θ))^c (ρ e^(i θ))^(i d)
// where ρ=|x| and θ=arg(x)
// = ρ^c e^(−d θ) e^(i c θ) ρ^(i d)
// = p^c e^(−d θ) (cos(c θ)
// + i sin(c θ)) (cos(d ln(ρ)) + i sin(d ln(ρ)))
// = p^c e^(−d θ) (
// cos(c θ) cos(d ln(ρ)) − sin(c θ) sin(d ln(ρ))
// + i(cos(c θ) sin(d ln(ρ)) + sin(c θ) cos(d ln(ρ))))
// = p^c e^(−d θ) (cos(c θ + d ln(ρ)) + i sin(c θ + d ln(ρ)))
// = from_polar(p^c e^(−d θ), c θ + d ln(ρ))
let (r, theta) = self.to_polar();
Self::from_polar(
r.powf(exp.re) * (-exp.im * theta).exp(),
exp.re * theta + exp.im * r.ln(),
)
if exp.is_zero() {
return Self::one();
}
// formula: x^y = exp(y * ln(x))
(exp * self.ln()).exp()
}

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

#[cfg(any(feature = "std", feature = "libm"))]
pub(crate) mod float {

use core::f64::INFINITY;

use super::*;
use num_traits::{Float, Pow};

Expand Down Expand Up @@ -1908,6 +1903,19 @@ pub(crate) mod test {
Complex::new(1.65826, -0.33502),
1e-5
));
let z = Complex::new(0.0, 0.0);
assert!(close(z.powc(b), z));
assert!(z.powc(Complex64::new(0., INFINITY)).is_nan());
assert!(z.powc(Complex64::new(10., INFINITY)).is_nan());
assert!(z.powc(Complex64::new(INFINITY, INFINITY)).is_nan());
assert!(close(z.powc(Complex64::new(INFINITY, 0.)), z));
assert!(z.powc(Complex64::new(-1., 0.)).re.is_infinite());
assert!(z.powc(Complex64::new(-1., 0.)).im.is_nan());

for c in all_consts.iter() {
assert_eq!(c.powc(_0_0i), _1_0i);
}
assert_eq!(_nan_nani.powc(_0_0i), _1_0i);
}

#[test]
Expand All @@ -1917,6 +1925,11 @@ pub(crate) mod test {
assert!(close_to_tol(c.powf(3.5), expected, 1e-5));
assert!(close_to_tol(Pow::pow(c, 3.5_f64), expected, 1e-5));
assert!(close_to_tol(Pow::pow(c, 3.5_f32), expected, 1e-5));

for c in all_consts.iter() {
assert_eq!(c.powf(0.0), _1_0i);
}
assert_eq!(_nan_nani.powf(0.0), _1_0i);
}

#[test]
Expand Down

0 comments on commit a78ab81

Please sign in to comment.