Skip to main content

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}