Skip to content

Commit a79aaf6

Browse files
committed
feat(solver): use heap-allocated vector as stack
1 parent 704baac commit a79aaf6

File tree

1 file changed

+15
-8
lines changed

1 file changed

+15
-8
lines changed

core/compiler/src/solver.rs

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ pub struct Solver {
2020
// Solved and unsolved vars are separate to reduce overhead of many solved variables.
2121
solved_vars: IndexMap<Var, f64>,
2222
unsolved_vars: IndexSet<Var>,
23+
back_substitute_stack: Vec<ConstraintId>,
2324
inconsistent_constraints: IndexSet<ConstraintId>,
2425
invalid_rounding: IndexSet<Var>,
2526
}
@@ -85,18 +86,24 @@ impl Solver {
8586
.insert(id);
8687
}
8788
self.constraints.insert(id, expr);
88-
self.try_back_substitute(id);
89+
// Use explicit stack in heap-allocated vector to avoid stack overflow.
90+
self.back_substitute_stack.push(id);
91+
while !self.back_substitute_stack.is_empty() {
92+
self.try_back_substitute();
93+
}
8994
id
9095
}
9196

9297
// Tries to back substitute using the given [`ConstraintId`].
93-
pub fn try_back_substitute(&mut self, constraint_id: ConstraintId) {
98+
pub fn try_back_substitute(&mut self) {
9499
// If coefficient length is not 1, do nothing.
95-
if let Some(constraint) = self.constraints.get_mut(&constraint_id) {
100+
if let Some(id) = self.back_substitute_stack.pop()
101+
&& let Some(constraint) = self.constraints.get_mut(&id)
102+
{
96103
constraint.simplify(&self.solved_vars);
97104
if constraint.coeffs.is_empty() && !relative_eq!(constraint.constant, 0.) {
98-
self.inconsistent_constraints.insert(constraint_id);
99-
self.constraints.swap_remove(&constraint_id);
105+
self.inconsistent_constraints.insert(id);
106+
self.constraints.swap_remove(&id);
100107
return;
101108
}
102109
if constraint.coeffs.len() != 1 {
@@ -108,7 +115,7 @@ impl Solver {
108115
let val = -constraint.constant / coeff;
109116
if let Some(old_val) = self.solved_vars.get(&var) {
110117
if relative_ne!(*old_val, val, epsilon = EPSILON) {
111-
self.inconsistent_constraints.insert(constraint_id);
118+
self.inconsistent_constraints.insert(id);
112119
}
113120
} else {
114121
let rounded_val = round(val);
@@ -117,7 +124,7 @@ impl Solver {
117124
}
118125
self.solve_var(var, rounded_val);
119126
}
120-
self.constraints.swap_remove(&constraint_id);
127+
self.constraints.swap_remove(&id);
121128
for constraint in self
122129
.var_to_constraints
123130
.get(&var)
@@ -126,7 +133,7 @@ impl Solver {
126133
.copied()
127134
.collect_vec()
128135
{
129-
self.try_back_substitute(constraint);
136+
self.back_substitute_stack.push(constraint);
130137
}
131138
}
132139
}

0 commit comments

Comments
 (0)