Skip to content

Commit 4455fa1

Browse files
committed
Switch to just computing angle on complex numbers
1 parent 967a715 commit 4455fa1

File tree

3 files changed

+58
-106
lines changed

3 files changed

+58
-106
lines changed

src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1849,8 +1849,6 @@ mod impl_2d;
18491849
mod impl_dyn;
18501850

18511851
mod numeric;
1852-
#[cfg(feature = "std")]
1853-
pub use crate::numeric::HasAngle;
18541852

18551853
pub mod linalg;
18561854

src/numeric/impl_float_maths.rs

Lines changed: 58 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,12 @@
11
// Element-wise methods for ndarray
22

33
#[cfg(feature = "std")]
4-
use num_complex::{Complex32, Complex64};
4+
use num_complex::Complex;
55
#[cfg(feature = "std")]
6-
use num_traits::Float;
6+
use num_traits::{Float, Zero};
77

88
use crate::imp_prelude::*;
99

10-
/// Trait for types that can generalize the phase angle (argument)
11-
/// calculation for both real floats and complex numbers.
12-
#[cfg(feature = "std")]
13-
pub trait HasAngle
14-
{
15-
/// The type of the associated angle.
16-
type Angle;
17-
18-
/// Return the phase angle (argument) of the value
19-
fn to_angle(&self) -> Self::Angle;
20-
}
21-
22-
#[cfg(feature = "std")]
23-
impl HasAngle for f32
24-
{
25-
type Angle = Self;
26-
27-
#[inline]
28-
fn to_angle(&self) -> Self
29-
{
30-
0f32.atan2(*self)
31-
}
32-
}
33-
34-
#[cfg(feature = "std")]
35-
impl HasAngle for f64
36-
{
37-
type Angle = Self;
38-
39-
#[inline]
40-
fn to_angle(&self) -> Self
41-
{
42-
0f64.atan2(*self)
43-
}
44-
}
45-
46-
#[cfg(feature = "std")]
47-
impl HasAngle for Complex32
48-
{
49-
type Angle = f32;
50-
51-
#[inline]
52-
fn to_angle(&self) -> Self::Angle
53-
{
54-
self.im.atan2(self.re)
55-
}
56-
}
57-
58-
#[cfg(feature = "std")]
59-
impl HasAngle for Complex64
60-
{
61-
type Angle = f64;
62-
63-
#[inline]
64-
fn to_angle(&self) -> Self::Angle
65-
{
66-
self.im.atan2(self.re)
67-
}
68-
}
69-
7010
#[cfg(feature = "std")]
7111
macro_rules! boolean_ops {
7212
($(#[$meta1:meta])* fn $func:ident
@@ -229,20 +169,71 @@ where
229169
}
230170
}
231171

172+
#[cfg(feature = "std")]
173+
impl<A, D> ArrayRef<A, D>
174+
where
175+
D: Dimension,
176+
A: Clone + Zero,
177+
{
178+
/// Map the array into the real part of a complex array; the imaginary part is 0.
179+
///
180+
/// # Example
181+
/// ```
182+
/// use ndarray::*;
183+
///
184+
/// let arr = array![1.0, -1.0, 0.0];
185+
/// let complex = arr.to_complex_re();
186+
///
187+
/// assert_eq!(complex[0], Complex::new(1.0, 0.0));
188+
/// assert_eq!(complex[1], Complex::new(-1.0, 0.0));
189+
/// assert_eq!(complex[2], Complex::new(0.0, 0.0));
190+
/// ```
191+
///
192+
/// # See Also
193+
/// [ArrayRef::to_complex_im]
194+
#[must_use = "method returns a new array and does not mutate the original value"]
195+
pub fn to_complex_re(&self) -> Array<Complex<A>, D>
196+
{
197+
self.mapv(|v| Complex::new(v, A::zero()))
198+
}
199+
200+
/// Map the array into the imaginary part of a complex array; the real part is 0.
201+
///
202+
/// # Example
203+
/// ```
204+
/// use ndarray::*;
205+
///
206+
/// let arr = array![1.0, -1.0, 0.0];
207+
/// let complex = arr.to_complex_re();
208+
///
209+
/// assert_eq!(complex[0], Complex::new(0.0, 1.0));
210+
/// assert_eq!(complex[1], Complex::new(0.0, -1.0));
211+
/// assert_eq!(complex[2], Complex::new(0.0, 0.0));
212+
/// ```
213+
///
214+
/// # See Also
215+
/// [ArrayRef::to_complex_re]
216+
#[must_use = "method returns a new array and does not mutate the original value"]
217+
pub fn to_complex_im(&self) -> Array<Complex<A>, D>
218+
{
219+
self.mapv(|v| Complex::new(A::zero(), v))
220+
}
221+
}
222+
232223
/// # Angle calculation methods for arrays
233224
///
234225
/// Methods for calculating phase angles of complex values in arrays.
235226
#[cfg(feature = "std")]
236-
impl<A, D> ArrayRef<A, D>
227+
impl<A, D> ArrayRef<Complex<A>, D>
237228
where
238229
D: Dimension,
239-
A: HasAngle,
230+
A: Float,
240231
{
241232
/// Return the [phase angle (argument)](https://en.wikipedia.org/wiki/Argument_(complex_analysis)) of complex values in the array.
242233
///
243234
/// This function always returns the same float type as was provided to it. Leaving the exact precision left to the user.
244235
/// The angles are returned in ``radians`` and in the range ``(-π, π]``.
245-
/// To get the angles in degrees, use the `to_degrees()` method on the resulting array.
236+
/// To get the angles in degrees, use the [`to_degrees()`][ArrayRef::to_degrees] method on the resulting array.
246237
///
247238
/// # Examples
248239
///
@@ -271,9 +262,9 @@ where
271262
/// assert!((angles[2] - PI/4.0).abs() < 1e-10);
272263
/// ```
273264
#[must_use = "method returns a new array and does not mutate the original value"]
274-
pub fn angle(&self) -> Array<A::Angle, D>
265+
pub fn angle(&self) -> Array<A, D>
275266
{
276-
self.map(A::to_angle)
267+
self.mapv(|v| v.im.atan2(v.re))
277268
}
278269
}
279270

@@ -327,28 +318,6 @@ mod angle_tests
327318
}};
328319
}
329320

330-
#[test]
331-
fn test_real_numbers_radians()
332-
{
333-
let arr = Array::from_vec(vec![1.0f64, -1.0, 0.0]);
334-
let angles = arr.angle();
335-
336-
assert_approx_eq!(angles[0], 0.0, 1e-10, "angle(1.0) should be 0");
337-
assert_approx_eq!(angles[1], PI, 1e-10, "angle(-1.0) should be π");
338-
assert_approx_eq!(angles[2], 0.0, 1e-10, "angle(0.0) should be 0");
339-
}
340-
341-
#[test]
342-
fn test_real_numbers_degrees()
343-
{
344-
let arr = Array::from_vec(vec![1.0f64, -1.0, 0.0]);
345-
let angles_deg = arr.angle().to_degrees();
346-
347-
assert_approx_eq!(angles_deg[0], 0.0, 1e-10, "angle(1.0) should be 0°");
348-
assert_approx_eq!(angles_deg[1], 180.0, 1e-10, "angle(-1.0) should be 180°");
349-
assert_approx_eq!(angles_deg[2], 0.0, 1e-10, "angle(0.0) should be 0°");
350-
}
351-
352321
#[test]
353322
fn test_complex_numbers_radians()
354323
{
@@ -421,18 +390,6 @@ mod angle_tests
421390
assert_approx_eq!(a[3], -PI / 2.0, 1e-10);
422391
}
423392

424-
#[test]
425-
fn test_mixed_precision()
426-
{
427-
let arr_f32 = Array::from_vec(vec![1.0f32, -1.0f32]);
428-
let arr_f64 = Array::from_vec(vec![1.0f64, -1.0f64]);
429-
let a32 = arr_f32.angle();
430-
let a64 = arr_f64.angle();
431-
432-
assert_approx_eq!(a32[0] as f64, a64[0], 1e-6);
433-
assert_approx_eq!(a32[1] as f64, a64[1], 1e-6);
434-
}
435-
436393
#[test]
437394
fn test_range_validation()
438395
{

src/numeric/mod.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
11
mod impl_numeric;
22

33
mod impl_float_maths;
4-
5-
#[cfg(feature = "std")]
6-
pub use self::impl_float_maths::HasAngle;

0 commit comments

Comments
 (0)