1#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
5pub enum MathClass {
6 Ord, Op, Bin, Rel, Open, Close, Punct, Inner, }
15
16#[rustfmt::skip]
25const SPACING_TABLE: [[i8; 8]; 8] = [
26[ 0, 3, 4, 5, 0, 0, 0, 3],
28[ 3, 4, 0, 5, 0, 0, 0, 3],
29[ 4, 4, 0, 0, 4, 0, 0, 4],
30[ 5, 5, 0, 0, 5, 0, 0, 5],
31[ 0, 0, 0, 0, 0, 0, 0, 0],
32[ 0, 3, 4, 5, 0, 0, 0, 3],
33[ 3, 3, 0, 5, 3, 3, 3, 3],
34[ 3, 3, 4, 5, 3, 0, 3, 3],
35];
36
37#[rustfmt::skip]
40const TIGHT_SPACING_TABLE: [[i8; 8]; 8] = [
41[ 0, 3, 0, 0, 0, 0, 0, 0],
43[ 3, 3, 0, 0, 0, 0, 0, 0],
44[ 0, 0, 0, 0, 0, 0, 0, 0],
45[ 0, 0, 0, 0, 0, 0, 0, 0],
46[ 0, 0, 0, 0, 0, 0, 0, 0],
47[ 0, 3, 0, 0, 0, 0, 0, 0],
48[ 0, 0, 0, 0, 0, 0, 0, 0],
49[ 0, 3, 0, 0, 0, 0, 0, 0],
50];
51
52impl MathClass {
53 fn index(self) -> usize {
54 match self {
55 Self::Ord => 0,
56 Self::Op => 1,
57 Self::Bin => 2,
58 Self::Rel => 3,
59 Self::Open => 4,
60 Self::Close => 5,
61 Self::Punct => 6,
62 Self::Inner => 7,
63 }
64 }
65}
66
67pub fn atom_spacing(left: MathClass, right: MathClass, tight: bool) -> f64 {
72 let table = if tight {
73 &TIGHT_SPACING_TABLE
74 } else {
75 &SPACING_TABLE
76 };
77 table[left.index()][right.index()] as f64
78}
79
80pub fn mu_to_em(mu: f64, quad: f64) -> f64 {
82 mu * quad / 18.0
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88
89 #[test]
90 fn test_ord_bin_spacing() {
91 assert_eq!(atom_spacing(MathClass::Ord, MathClass::Bin, false), 4.0);
92 }
93
94 #[test]
95 fn test_ord_rel_spacing() {
96 assert_eq!(atom_spacing(MathClass::Ord, MathClass::Rel, false), 5.0);
97 }
98
99 #[test]
100 fn test_ord_ord_no_spacing() {
101 assert_eq!(atom_spacing(MathClass::Ord, MathClass::Ord, false), 0.0);
102 }
103
104 #[test]
105 fn test_tight_eliminates_most_spacing() {
106 assert_eq!(atom_spacing(MathClass::Ord, MathClass::Bin, true), 0.0);
107 assert_eq!(atom_spacing(MathClass::Ord, MathClass::Rel, true), 0.0);
108 }
109
110 #[test]
111 fn test_tight_keeps_op_spacing() {
112 assert_eq!(atom_spacing(MathClass::Ord, MathClass::Op, true), 3.0);
113 assert_eq!(atom_spacing(MathClass::Op, MathClass::Ord, true), 3.0);
114 }
115
116 #[test]
117 fn test_mu_to_em() {
118 let quad = 1.0;
119 assert!((mu_to_em(3.0, quad) - 3.0 / 18.0).abs() < 1e-10);
120 assert!((mu_to_em(4.0, quad) - 4.0 / 18.0).abs() < 1e-10);
121 assert!((mu_to_em(5.0, quad) - 5.0 / 18.0).abs() < 1e-10);
122 }
123}