1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
use crate::graph::FxMapGraph;

#[derive(Default, Debug, Clone)]
pub struct State {
    pub degrees: Vec<isize>,
    pub next_sigma: Vec<usize>,
    pub next_on_path: Vec<usize>,
    pub visited: Vec<bool>,
    pub pre: Vec<usize>,
    pub lowpt: Vec<usize>,
    pub count: usize,
    pub num_descendants: Vec<usize>,
    pub path_u: usize,
    pub sigma: Vec<Vec<usize>>,
}

impl State {
    pub fn initialize(graph: &FxMapGraph) -> State {
        let num_nodes = graph.len();

        State {
            count: 1,
            next_sigma: vec![0; num_nodes],
            next_on_path: vec![0; num_nodes],
            pre: vec![0; num_nodes],
            lowpt: vec![0; num_nodes],
            num_descendants: vec![1; num_nodes],
            degrees: vec![0; num_nodes],
            visited: vec![false; num_nodes],
            sigma: Vec::new(),
            path_u: 0,
        }
    }

    pub fn mut_recur(&mut self, w: usize) {
        assert!(w < self.visited.len());
        unsafe {
            *self.visited.get_unchecked_mut(w) = true;
            *self.next_sigma.get_unchecked_mut(w) = w;
            *self.next_on_path.get_unchecked_mut(w) = w;
            *self.pre.get_unchecked_mut(w) = self.count;
            *self.lowpt.get_unchecked_mut(w) = self.count;
        }
        self.count += 1;
    }

    pub fn components(&self) -> &Vec<Vec<usize>> {
        &self.sigma
    }

    pub fn is_back_edge(&self, u: usize, v: usize) -> bool {
        self.pre[u] > self.pre[v]
    }

    pub fn is_null_path(&self, u: usize) -> bool {
        self.next_on_path[u] == u
    }

    pub fn absorb_path(
        &mut self,
        root: usize,
        path: usize,
        end: Option<usize>,
    ) {
        if Some(root) != end {
            let mut current = root;
            let mut step = path;
            while current != step {
                unsafe {
                    *self.degrees.get_unchecked_mut(root) +=
                        *self.degrees.get_unchecked_mut(step) - 2;
                    self.next_sigma.swap(root, step);
                    current = step;
                    if Some(step) != end {
                        step = *self.next_on_path.get_unchecked(step);
                    }
                    // self.degrees[root] += self.degrees[step] - 2;
                    // self.next_sigma.swap(root, step);
                    // current = step;
                    // if Some(step) != end {
                    //     step = self.next_on_path[step];
                    // }
                }
            }
        }
    }

    pub fn sigma_iter(&self, start: usize) -> SigmaIter<'_> {
        SigmaIter::new(self, start)
    }

    pub fn add_component(&mut self, start: usize) {
        self.sigma.push(self.sigma_iter(start).collect());
    }
}

// Struct representing an iterator over a node's sigma set
pub struct SigmaIter<'a> {
    start: usize,
    current: usize,
    next_sigma: &'a [usize],
    done: bool,
}

impl<'a> SigmaIter<'a> {
    fn new(state: &'a State, node: usize) -> SigmaIter<'a> {
        let next_sigma = &state.next_sigma;
        SigmaIter {
            start: node,
            current: next_sigma[node],
            next_sigma,
            done: false,
        }
    }
}

impl<'a> Iterator for SigmaIter<'a> {
    type Item = usize;

    fn next(&mut self) -> Option<usize> {
        if self.done {
            None
        } else {
            if self.current == self.start {
                self.done = true;
            }

            self.current = self.next_sigma[self.current];
            Some(self.current)
        }
    }
}