qsym2/target/tensor/
axialvector.rs1use std::fmt;
4
5use approx;
6use derive_builder::Builder;
7use nalgebra::Vector3;
8use ndarray_linalg::types::Lapack;
9use num_complex::{Complex, ComplexFloat};
10use num_traits::float::{Float, FloatConst};
11
12#[cfg(test)]
13#[path = "axialvector_tests.rs"]
14mod axialvector_tests;
15
16#[path = "axialvector_analysis.rs"]
17pub mod axialvector_analysis;
18#[path = "axialvector_transformation.rs"]
19mod axialvector_transformation;
20
21#[derive(Debug, PartialEq, Eq, Clone)]
23pub enum TimeParity {
24 Even,
26
27 Odd,
29}
30
31impl fmt::Display for TimeParity {
35 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
36 match self {
37 TimeParity::Even => write!(f, "time-even"),
38 TimeParity::Odd => write!(f, "time-odd"),
39 }
40 }
41}
42
43#[derive(Builder, Clone)]
49pub struct AxialVector3<T>
50where
51 T: ComplexFloat + Lapack,
52{
53 components: Vector3<T>,
55
56 time_parity: TimeParity,
58
59 threshold: <T as ComplexFloat>::Real,
61}
62
63impl<T> AxialVector3<T>
64where
65 T: ComplexFloat + Clone + Lapack,
66{
67 pub fn builder() -> AxialVector3Builder<T> {
69 AxialVector3Builder::default()
70 }
71
72 pub fn components(&self) -> &Vector3<T> {
74 &self.components
75 }
76
77 pub fn time_parity(&self) -> &TimeParity {
79 &self.time_parity
80 }
81
82 pub fn threshold(&self) -> <T as ComplexFloat>::Real {
84 self.threshold
85 }
86}
87
88impl<T> From<AxialVector3<T>> for AxialVector3<Complex<T>>
96where
97 T: Float + FloatConst + Lapack,
98 Complex<T>: Lapack,
99{
100 fn from(value: AxialVector3<T>) -> Self {
101 AxialVector3::<Complex<T>>::builder()
102 .components(value.components.map(Complex::from))
103 .time_parity(value.time_parity.clone())
104 .threshold(value.threshold)
105 .build()
106 .expect("Unable to construct a complex axial vector in three dimensions.")
107 }
108}
109
110impl<T> PartialEq for AxialVector3<T>
114where
115 T: ComplexFloat<Real = f64> + Lapack,
116{
117 fn eq(&self, other: &Self) -> bool {
118 let thresh = (self.threshold * other.threshold).sqrt();
119 let components_eq = approx::relative_eq!(
120 (&self.components - &other.components)
121 .map(|x| ComplexFloat::abs(x).powi(2))
122 .sum()
123 .sqrt(),
124 0.0,
125 epsilon = thresh,
126 max_relative = thresh,
127 );
128 self.time_parity == other.time_parity && components_eq
129 }
130}
131
132impl<T> Eq for AxialVector3<T> where T: ComplexFloat<Real = f64> + Lapack {}
136
137impl<T> fmt::Debug for AxialVector3<T>
141where
142 T: fmt::Debug + ComplexFloat + Lapack,
143{
144 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
145 write!(
146 f,
147 "AxialVector3({})({:+.7}, {:+.7}, {:+.7})",
148 self.time_parity, self.components[0], self.components[1], self.components[2],
149 )
150 }
151}
152
153impl<T> fmt::Display for AxialVector3<T>
157where
158 T: fmt::Display + ComplexFloat + Lapack,
159{
160 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
161 write!(
162 f,
163 "AxialVector3({})({:+.3}, {:+.3}, {:+.3})",
164 self.time_parity, self.components[0], self.components[1], self.components[2],
165 )
166 }
167}