1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
#[cfg(feature = "arbitrary")]
use quickcheck::{Arbitrary, Gen};
use num::One;
use num_complex::Complex;
use rand::{Rand, Rng};
use alga::general::Real;
use core::{DefaultAllocator, Vector};
use core::dimension::{U1, U2};
use core::storage::Storage;
use core::allocator::Allocator;
use geometry::{UnitComplex, Rotation};
impl<N: Real> UnitComplex<N> {
#[inline]
pub fn identity() -> Self {
Self::new_unchecked(Complex::new(N::one(), N::zero()))
}
#[inline]
pub fn new(angle: N) -> Self {
let (sin, cos) = angle.sin_cos();
Self::from_cos_sin_unchecked(cos, sin)
}
#[inline]
pub fn from_angle(angle: N) -> Self {
Self::new(angle)
}
#[inline]
pub fn from_cos_sin_unchecked(cos: N, sin: N) -> Self {
UnitComplex::new_unchecked(Complex::new(cos, sin))
}
#[inline]
pub fn from_scaled_axis<SB: Storage<N, U1, U1>>(axisangle: Vector<N, U1, SB>) -> Self {
Self::from_angle(axisangle[0])
}
#[inline]
pub fn from_complex(q: Complex<N>) -> Self {
Self::from_complex_and_get(q).0
}
#[inline]
pub fn from_complex_and_get(q: Complex<N>) -> (Self, N) {
let norm = (q.im * q.im + q.re * q.re).sqrt();
(Self::new_unchecked(q / norm), norm)
}
#[inline]
pub fn from_rotation_matrix(rotmat: &Rotation<N, U2>) -> Self
where DefaultAllocator: Allocator<N, U2, U2> {
Self::new_unchecked(Complex::new(rotmat[(0, 0)], rotmat[(1, 0)]))
}
#[inline]
pub fn rotation_between<SB, SC>(a: &Vector<N, U2, SB>, b: &Vector<N, U2, SC>) -> Self
where SB: Storage<N, U2, U1>,
SC: Storage<N, U2, U1> {
Self::scaled_rotation_between(a, b, N::one())
}
#[inline]
pub fn scaled_rotation_between<SB, SC>(a: &Vector<N, U2, SB>, b: &Vector<N, U2, SC>, s: N) -> Self
where SB: Storage<N, U2, U1>,
SC: Storage<N, U2, U1> {
if let (Some(na), Some(nb)) = (a.try_normalize(N::zero()), b.try_normalize(N::zero())) {
let sang = na.perp(&nb);
let cang = na.dot(&nb);
Self::from_angle(sang.atan2(cang) * s)
}
else {
Self::identity()
}
}
}
impl<N: Real> One for UnitComplex<N> {
#[inline]
fn one() -> Self {
Self::identity()
}
}
impl<N: Real + Rand> Rand for UnitComplex<N> {
#[inline]
fn rand<R: Rng>(rng: &mut R) -> Self {
UnitComplex::from_angle(N::rand(rng))
}
}
#[cfg(feature="arbitrary")]
impl<N: Real + Arbitrary> Arbitrary for UnitComplex<N> {
#[inline]
fn arbitrary<G: Gen>(g: &mut G) -> Self {
UnitComplex::from_angle(N::arbitrary(g))
}
}