Skip to content

Commit b7b756b

Browse files
committed
Refactor helper functions of PiecewiseLinearFn to have clearer responsibilities
1 parent 8b75731 commit b7b756b

File tree

1 file changed

+24
-23
lines changed

1 file changed

+24
-23
lines changed

src/misc.rs

Lines changed: 24 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -78,33 +78,29 @@ impl PiecewiseLinearFn {
7878
}
7979

8080
/// Replaces the represented function with the maximum of itself and a provided line
81-
pub fn max_with(&mut self, slope: f64, intercept: f64) {
82-
self.recent_lines.push((slope, intercept));
81+
pub fn max_with(&mut self, new_m: f64, new_b: f64) {
82+
self.recent_lines.push((new_m, new_b));
8383
}
8484

85-
fn update_envelope(&mut self) {
86-
self.recent_lines.sort_unstable_by(asserting_cmp);
87-
self.intersections.clear();
88-
89-
for (new_m, new_b) in merge_sorted(self.recent_lines.drain(..), self.sorted_lines.drain(..))
90-
{
91-
while let Some(&(last_m, last_b)) = self.sorted_lines.last() {
92-
// If slopes are equal, get rid of the old line as its intercept is lower
93-
if (new_m - last_m).abs() > 1e-9 {
94-
let intr = (new_b - last_b) / (last_m - new_m);
95-
if self.intersections.last() < Some(&intr) {
96-
self.intersections.push(intr);
97-
break;
98-
}
85+
/// Similar to max_with but requires that (new_m, new_b) be the largest pair so far
86+
fn max_with_sorted(&mut self, new_m: f64, new_b: f64) {
87+
while let Some(&(last_m, last_b)) = self.sorted_lines.last() {
88+
// If slopes are equal, get rid of the old line as its intercept is lower
89+
if (new_m - last_m).abs() > 1e-9 {
90+
let intersect = (new_b - last_b) / (last_m - new_m);
91+
if self.intersections.last() < Some(&intersect) {
92+
self.intersections.push(intersect);
93+
break;
9994
}
100-
self.intersections.pop();
101-
self.sorted_lines.pop();
10295
}
103-
self.sorted_lines.push((new_m, new_b));
96+
self.intersections.pop();
97+
self.sorted_lines.pop();
10498
}
99+
self.sorted_lines.push((new_m, new_b));
105100
}
106101

107-
fn eval_helper(&self, x: f64) -> f64 {
102+
/// Evaluates the function at x
103+
fn eval_unoptimized(&self, x: f64) -> f64 {
108104
let idx = slice_lower_bound(&self.intersections, &x);
109105
self.recent_lines
110106
.iter()
@@ -114,12 +110,17 @@ impl PiecewiseLinearFn {
114110
.unwrap_or(-1e18)
115111
}
116112

117-
/// Evaluates the function at x
113+
/// Evaluates the function at x with good amortized runtime
118114
pub fn evaluate(&mut self, x: f64) -> f64 {
119115
if self.recent_lines.len() > self.merge_threshold {
120-
self.update_envelope();
116+
self.recent_lines.sort_unstable_by(asserting_cmp);
117+
self.intersections.clear();
118+
let all_lines = merge_sorted(self.recent_lines.drain(..), self.sorted_lines.drain(..));
119+
for (new_m, new_b) in all_lines {
120+
self.max_with_sorted(new_m, new_b);
121+
}
121122
}
122-
self.eval_helper(x)
123+
self.eval_unoptimized(x)
123124
}
124125
}
125126

0 commit comments

Comments
 (0)