whitaker_common/test_support/decomposition_vector_algebra.rs
1//! Observable vector-algebra seams for decomposition advice tests.
2
3use crate::MethodProfile;
4use crate::decomposition_advice::{build_feature_vector, dot_product};
5
6/// Observable runtime vector-algebra results for two methods.
7///
8/// # Examples
9///
10/// ```ignore
11/// use whitaker_common::test_support::decomposition::{MethodInput, method_vector_algebra, profile};
12///
13/// let left = profile(MethodInput {
14/// name: "parse_tokens",
15/// fields: &["grammar"],
16/// signature_types: &[],
17/// local_types: &[],
18/// domains: &[],
19/// });
20/// let right = profile(MethodInput {
21/// name: "parse_nodes",
22/// fields: &["grammar"],
23/// signature_types: &[],
24/// local_types: &[],
25/// domains: &[],
26/// });
27///
28/// let report = method_vector_algebra(&left, &right);
29/// assert_eq!(report.left_dot_right(), report.right_dot_left());
30/// assert!(report.left_norm_squared() > 0);
31/// ```
32#[derive(Clone, Copy, Debug, Eq, PartialEq)]
33pub struct MethodVectorAlgebraReport {
34 left_dot_right: u64,
35 right_dot_left: u64,
36 left_norm_squared: u64,
37 right_norm_squared: u64,
38}
39
40impl MethodVectorAlgebraReport {
41 /// Returns the result of [`MethodVectorAlgebraReport::left_dot_right`].
42 ///
43 /// This is the dot product of the left and right method vectors.
44 ///
45 /// ```rust
46 /// use whitaker_common::test_support::decomposition::{MethodInput, method_vector_algebra, profile};
47 ///
48 /// let left = profile(MethodInput {
49 /// name: "parse_tokens",
50 /// fields: &["grammar"],
51 /// signature_types: &[],
52 /// local_types: &[],
53 /// domains: &[],
54 /// });
55 /// let right = profile(MethodInput {
56 /// name: "parse_nodes",
57 /// fields: &["grammar"],
58 /// signature_types: &[],
59 /// local_types: &[],
60 /// domains: &[],
61 /// });
62 ///
63 /// let report = method_vector_algebra(&left, &right);
64 /// assert_eq!(report.left_dot_right(), 40);
65 /// ```
66 #[must_use]
67 pub fn left_dot_right(self) -> u64 {
68 self.left_dot_right
69 }
70
71 /// Returns the result of [`MethodVectorAlgebraReport::right_dot_left`].
72 ///
73 /// This is the dot product of the right and left method vectors.
74 ///
75 /// ```rust
76 /// use whitaker_common::test_support::decomposition::{MethodInput, method_vector_algebra, profile};
77 ///
78 /// let left = profile(MethodInput {
79 /// name: "parse_tokens",
80 /// fields: &["grammar"],
81 /// signature_types: &[],
82 /// local_types: &[],
83 /// domains: &[],
84 /// });
85 /// let right = profile(MethodInput {
86 /// name: "parse_nodes",
87 /// fields: &["grammar"],
88 /// signature_types: &[],
89 /// local_types: &[],
90 /// domains: &[],
91 /// });
92 ///
93 /// let report = method_vector_algebra(&left, &right);
94 /// assert_eq!(report.right_dot_left(), 40);
95 /// ```
96 #[must_use]
97 pub fn right_dot_left(self) -> u64 {
98 self.right_dot_left
99 }
100
101 /// Returns the result of [`MethodVectorAlgebraReport::left_norm_squared`].
102 ///
103 /// This is the squared L2 norm of the left method vector.
104 ///
105 /// ```rust
106 /// use whitaker_common::test_support::decomposition::{MethodInput, method_vector_algebra, profile};
107 ///
108 /// let left = profile(MethodInput {
109 /// name: "parse_tokens",
110 /// fields: &["grammar"],
111 /// signature_types: &[],
112 /// local_types: &[],
113 /// domains: &[],
114 /// });
115 /// let right = profile(MethodInput {
116 /// name: "parse_nodes",
117 /// fields: &["grammar"],
118 /// signature_types: &[],
119 /// local_types: &[],
120 /// domains: &[],
121 /// });
122 ///
123 /// let report = method_vector_algebra(&left, &right);
124 /// assert_eq!(report.left_norm_squared(), 44);
125 /// ```
126 #[must_use]
127 pub fn left_norm_squared(self) -> u64 {
128 self.left_norm_squared
129 }
130
131 /// Returns the result of [`MethodVectorAlgebraReport::right_norm_squared`].
132 ///
133 /// This is the squared L2 norm of the right method vector.
134 ///
135 /// ```rust
136 /// use whitaker_common::test_support::decomposition::{MethodInput, method_vector_algebra, profile};
137 ///
138 /// let left = profile(MethodInput {
139 /// name: "parse_tokens",
140 /// fields: &["grammar"],
141 /// signature_types: &[],
142 /// local_types: &[],
143 /// domains: &[],
144 /// });
145 /// let right = profile(MethodInput {
146 /// name: "parse_nodes",
147 /// fields: &["grammar"],
148 /// signature_types: &[],
149 /// local_types: &[],
150 /// domains: &[],
151 /// });
152 ///
153 /// let report = method_vector_algebra(&left, &right);
154 /// assert_eq!(report.right_norm_squared(), 44);
155 /// ```
156 #[must_use]
157 pub fn right_norm_squared(self) -> u64 {
158 self.right_norm_squared
159 }
160}
161
162/// Computes the shipped vector-algebra helper values for two methods.
163///
164/// This helper exists for behaviour tests that need to observe the runtime
165/// `dot_product` and `norm_squared` results without widening the production
166/// decomposition API.
167///
168/// # Examples
169///
170/// ```ignore
171/// use whitaker_common::test_support::decomposition::{MethodInput, method_vector_algebra, profile};
172///
173/// let left = profile(MethodInput {
174/// name: "parse_tokens",
175/// fields: &["grammar"],
176/// signature_types: &[],
177/// local_types: &[],
178/// domains: &[],
179/// });
180/// let right = profile(MethodInput {
181/// name: "save_to_disk",
182/// fields: &[],
183/// signature_types: &[],
184/// local_types: &["PathBuf"],
185/// domains: &["std::fs"],
186/// });
187///
188/// let report = method_vector_algebra(&left, &right);
189/// assert_eq!(report.left_dot_right(), 0);
190/// ```
191#[must_use]
192pub fn method_vector_algebra(
193 left: &MethodProfile,
194 right: &MethodProfile,
195) -> MethodVectorAlgebraReport {
196 let left_vector = build_feature_vector(left);
197 let right_vector = build_feature_vector(right);
198
199 MethodVectorAlgebraReport {
200 left_dot_right: dot_product(left_vector.weights(), right_vector.weights()),
201 right_dot_left: dot_product(right_vector.weights(), left_vector.weights()),
202 left_norm_squared: left_vector.norm_squared(),
203 right_norm_squared: right_vector.norm_squared(),
204 }
205}