csvx/table/
calc.rs

1use super::*;
2
3impl Table {
4    /// Calculate recursive
5    pub fn calc(
6        x: usize,
7        y: usize,
8        tree_table: &mut Vec<Vec<Box<ThreadSafeNode>>>,
9        ref_src_table: &mut Vec<Vec<Vec<(usize, usize)>>>,
10        dependents_table: &mut Vec<Vec<HashMap<(usize, usize), u32>>>,
11        calculated_table: &mut Vec<Vec<Value>>,
12        walked_position: &mut Vec<(usize, usize)>,
13    ) {
14        walked_position.push((x, y));
15
16        calculated_table[y][x] =
17            if ref_src_table[y][x]
18                .iter()
19                .fold(false, |b, (x_of_target, y_of_target)| {
20                    b || walked_position.contains(&(*x_of_target, *y_of_target))
21                })
22            {
23                Value::Error
24            } else {
25                // Calculate current item
26                let (calculated_value, old_dependents, new_dependents) =
27                    tree_table[y][x].calc(&calculated_table);
28
29                // Increment reference count.
30                for (dependent_x, dependent_y) in new_dependents {
31                    if dependent_y < dependents_table.len()
32                        && dependent_x < dependents_table[dependent_y].len()
33                    {
34                        let entry = dependents_table[y][x]
35                            .entry((dependent_x, dependent_y))
36                            .or_insert(0);
37
38                        if *entry == 0 {
39                            ref_src_table[dependent_y][dependent_x].push((x, y));
40                        }
41
42                        *entry += 1;
43                    }
44                }
45
46                // Decrement reference count.
47                for (dependent_x, dependent_y) in old_dependents {
48                    if let (true, true, Some(n)) = (
49                        dependent_y < dependents_table.len(),
50                        dependent_x < dependents_table[dependent_y].len(),
51                        dependents_table[y][x].get_mut(&(dependent_x, dependent_y)),
52                    ) {
53                        *n -= 1;
54
55                        if *n == 0 {
56                            ref_src_table[dependent_y][dependent_x]
57                                .retain(|&(x_src, y_src)| x_src == x && y_src == y);
58                        }
59                    }
60                }
61
62                // Sweep unnecessary item
63                dependents_table[y][x].retain(|_, v| *v != 0);
64
65                calculated_value
66            };
67
68        for i in 0..ref_src_table[y][x].len() {
69            let (x_of_target, y_of_target) = ref_src_table[y][x][i];
70            let n_walks = walked_position.iter().fold(0, |b, walked_pos| {
71                if walked_pos == &(x_of_target, y_of_target) {
72                    b + 1
73                } else {
74                    b
75                }
76            });
77
78            if n_walks < 2 {
79                Self::calc(
80                    x_of_target,
81                    y_of_target,
82                    tree_table,
83                    ref_src_table,
84                    dependents_table,
85                    calculated_table,
86                    walked_position,
87                );
88            }
89        }
90    }
91}