fix '$skip_max_list'/4 (#1260)
This commit is contained in:
@@ -372,7 +372,7 @@ impl<'a> HeapPStrIter<'a> {
|
|||||||
match self.brent_st.step(next_hare) {
|
match self.brent_st.step(next_hare) {
|
||||||
Some(cycle_result) => {
|
Some(cycle_result) => {
|
||||||
debug_assert!(match cycle_result {
|
debug_assert!(match cycle_result {
|
||||||
CycleSearchResult::Cyclic(_) => true,
|
CycleSearchResult::Cyclic(..) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -432,7 +432,7 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn skip_max_list_cycle(&mut self, lam: usize) {
|
fn skip_max_list_cycle(&mut self, lam: usize) {
|
||||||
fn step(heap: &Heap, mut value: HeapCellValue) -> usize {
|
fn step(heap: &[HeapCellValue], mut value: HeapCellValue) -> usize {
|
||||||
loop {
|
loop {
|
||||||
read_heap_cell!(value,
|
read_heap_cell!(value,
|
||||||
(HeapCellValueTag::PStrLoc, h) => {
|
(HeapCellValueTag::PStrLoc, h) => {
|
||||||
@@ -455,27 +455,43 @@ impl MachineState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut hare = step(&self.heap, self.registers[3]);
|
let h = self.heap.len();
|
||||||
|
self.heap.push(self.registers[3]);
|
||||||
|
|
||||||
|
let mut hare = h;
|
||||||
let mut tortoise = hare;
|
let mut tortoise = hare;
|
||||||
|
|
||||||
for _ in 0 .. lam {
|
for _ in 0 .. lam {
|
||||||
hare = step(&self.heap, self.heap[hare]);
|
hare = step(&self.heap, self.heap[hare]);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut count = 1;
|
let mut prev_hare = hare;
|
||||||
|
|
||||||
while hare != tortoise {
|
while hare != tortoise {
|
||||||
|
prev_hare = hare;
|
||||||
hare = step(&self.heap, self.heap[hare]);
|
hare = step(&self.heap, self.heap[hare]);
|
||||||
tortoise = step(&self.heap, self.heap[tortoise]);
|
tortoise = step(&self.heap, self.heap[tortoise]);
|
||||||
|
|
||||||
count += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// now compute the num_steps of the list prefix until hare is
|
||||||
|
// reached in the fashion of a C do-while loop since hare
|
||||||
|
// may point to the beginning of a cycle.
|
||||||
|
|
||||||
|
let mut brent_st = BrentAlgState::new(h);
|
||||||
|
|
||||||
|
self.brents_alg_step(&mut brent_st);
|
||||||
|
|
||||||
|
while prev_hare != brent_st.hare {
|
||||||
|
self.brents_alg_step(&mut brent_st);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.heap.pop();
|
||||||
|
|
||||||
let target_n = self.store(self.deref(self.registers[1]));
|
let target_n = self.store(self.deref(self.registers[1]));
|
||||||
self.unify_fixnum(Fixnum::build_with(count), target_n);
|
self.unify_fixnum(Fixnum::build_with(brent_st.num_steps() as i64), target_n);
|
||||||
|
|
||||||
if !self.fail {
|
if !self.fail {
|
||||||
unify!(self, self.registers[4], self.heap[hare]);
|
unify!(self, self.registers[4], self.heap[prev_hare]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user