1mod types;
4pub use types::*;
5
6mod state;
7pub use state::*;
8
9mod rules;
10pub use rules::*;
11
12pub mod builtin;
14
15#[allow(unused_macros)]
17#[macro_export]
18macro_rules! j {
19 ($n:literal / 2) => {
20 $crate::quantum::J::half($n)
21 };
22 ($n:literal) => {
23 $crate::quantum::J::int($n)
24 };
25 ($($bad:tt)*) => {
26 compile_error!("expected j!(N) or j!(N/2) where N is an integer literal");
27 };
28}
29#[allow(unused_macros)]
31#[macro_export]
32macro_rules! s {
33 ($n:literal / 2) => {
34 $crate::quantum::S::half($n)
35 };
36 ($n:literal) => {
37 $crate::quantum::S::int($n)
38 };
39 ($($bad:tt)*) => {
40 compile_error!("expected s!(N) or s!(N/2) where N is an integer literal");
41 };
42}
43#[allow(unused_macros)]
45#[macro_export]
46macro_rules! m {
47 ($n:literal / 2) => {
48 $crate::quantum::M::half($n)
49 };
50 (- $n:literal / 2) => {
51 $crate::quantum::M::half(-$n)
52 };
53 ($n:literal) => {
54 $crate::quantum::M::int($n)
55 };
56 (- $n:literal) => {
57 $crate::quantum::M::int(-$n)
58 };
59 ($($bad:tt)*) => {
60 compile_error!(
61 "expected m!(N), m!(-N), m!(N/2), or m!(-N/2) where N is an integer literal"
62 );
63 };
64}
65#[allow(unused_macros)]
67#[macro_export]
68macro_rules! l {
69 ($n:literal) => {
70 $crate::quantum::L::int($n)
71 };
72 ($($bad:tt)*) => {
73 compile_error!("expected l!(N) where N is an integer literal");
74 };
75}
76
77#[cfg(test)]
78mod tests {
79 use std::str::FromStr;
80
81 use super::*;
82
83 #[test]
84 fn check_angular_momentum_macros() {
85 assert_eq!(J::int(1), j!(1));
86 assert_eq!(J::half(1), j!(1 / 2));
87 assert_eq!(S::int(1), s!(1));
88 assert_eq!(S::half(1), s!(1 / 2));
89 assert_eq!(M::int(1), m!(1));
90 assert_eq!(M::half(1), m!(1 / 2));
91 assert_eq!(M::int(-1), m!(-1));
92 assert_eq!(M::half(-1), m!(-1 / 2));
93 assert_eq!(L::int(1), l!(1));
94 }
95
96 #[test]
97 fn spin_state_accepts_integer_and_half_integer_values() {
98 let spin_one = j!(1);
99 let spin_half = j!(1 / 2);
100 assert_eq!(
101 SpinState::new(spin_one, m!(0))
102 .unwrap()
103 .projection()
104 .doubled(),
105 0
106 );
107 assert_eq!(
108 SpinState::new(spin_half, m!(-1 / 2))
109 .unwrap()
110 .projection()
111 .doubled(),
112 -1
113 );
114 }
115
116 #[test]
117 fn spin_state_rejects_invalid_projection() {
118 let spin_one = j!(1);
119 assert!(SpinState::new(spin_one, m!(4 / 2)).is_err());
120 assert!(SpinState::new(spin_one, m!(1 / 2)).is_err());
121 }
122
123 #[test]
124 fn angular_momenta_return_projection_values() {
125 assert_eq!(j!(1).projections(), vec![m!(-1), m!(0), m!(1)]);
126 assert_eq!(
127 j!(3 / 2).projections(),
128 vec![m!(-3 / 2), m!(-1 / 2), m!(1 / 2), m!(3 / 2)]
129 );
130 assert_eq!(l!(1).projections(), j!(1).projections());
131 }
132
133 #[test]
134 fn enum_displays() {
135 assert_eq!(format!("{}", Reflectivity::Positive), "+");
136 assert_eq!(format!("{}", Reflectivity::Negative), "-");
137 assert_eq!(format!("{}", MandelstamChannel::S), "s");
138 assert_eq!(format!("{}", MandelstamChannel::T), "t");
139 assert_eq!(format!("{}", MandelstamChannel::U), "u");
140 }
141
142 #[test]
143 fn enum_from_str() {
144 assert_eq!(Reflectivity::from_str("+").unwrap(), Reflectivity::Positive);
145 assert_eq!(
146 Reflectivity::from_str("pos").unwrap(),
147 Reflectivity::Positive
148 );
149 assert_eq!(
150 Reflectivity::from_str("plus").unwrap(),
151 Reflectivity::Positive
152 );
153 assert_eq!(
154 Reflectivity::from_str("Positive").unwrap(),
155 Reflectivity::Positive
156 );
157 assert_eq!(Reflectivity::from_str("-").unwrap(), Reflectivity::Negative);
158 assert_eq!(
159 Reflectivity::from_str("minus").unwrap(),
160 Reflectivity::Negative
161 );
162 assert_eq!(
163 Reflectivity::from_str("neg").unwrap(),
164 Reflectivity::Negative
165 );
166 assert_eq!(
167 Reflectivity::from_str("Negative").unwrap(),
168 Reflectivity::Negative
169 );
170 assert_eq!(
171 MandelstamChannel::from_str("S").unwrap(),
172 MandelstamChannel::S
173 );
174 assert_eq!(
175 MandelstamChannel::from_str("s").unwrap(),
176 MandelstamChannel::S
177 );
178 assert_eq!(
179 MandelstamChannel::from_str("T").unwrap(),
180 MandelstamChannel::T
181 );
182 assert_eq!(
183 MandelstamChannel::from_str("t").unwrap(),
184 MandelstamChannel::T
185 );
186 assert_eq!(
187 MandelstamChannel::from_str("U").unwrap(),
188 MandelstamChannel::U
189 );
190 assert_eq!(
191 MandelstamChannel::from_str("u").unwrap(),
192 MandelstamChannel::U
193 );
194 }
195}