sprs_rssn/
stack.rs

1/// Stack implementations tuned for the graph traversal algorithms
2/// encountered in sparse matrix solves/factorizations
3use std::default::Default;
4use std::slice;
5
6/// A double stack of fixed capacity, growing from the left to the right
7/// or conversely.
8///
9/// Used in sparse triangular / sparse vector solves, where it is guaranteed
10/// that the two parts of the stack cannot overlap.
11#[derive(Debug, Clone)]
12pub struct DStack<I> {
13    stacks: Vec<I>,
14    left_head: Option<usize>,
15    right_head: usize,
16}
17
18#[derive(Clone, Copy, PartialEq, Eq, Debug)]
19pub enum StackVal<I> {
20    Enter(I),
21    Exit(I),
22}
23
24impl<I: Default> Default for StackVal<I> {
25    fn default() -> Self {
26        Self::Enter(I::default())
27    }
28}
29
30impl<I> DStack<I>
31where
32    I: Clone,
33{
34    /// Create a new double stacked suited for containing at most n elements
35    pub fn with_capacity(n: usize) -> Self
36    where
37        I: Default,
38    {
39        assert!(n > 1);
40        Self {
41            stacks: vec![I::default(); n],
42            left_head: None,
43            right_head: n,
44        }
45    }
46
47    /// Capacity of the dstack
48    pub fn capacity(&self) -> usize {
49        self.stacks.len()
50    }
51
52    /// Test whether the left stack is empty
53    pub fn is_left_empty(&self) -> bool {
54        self.left_head.is_none()
55    }
56
57    /// Test whether the right stack is empty
58    pub fn is_right_empty(&self) -> bool {
59        self.right_head == self.capacity()
60    }
61
62    /// Push a value on the left stack
63    pub fn push_left(&mut self, value: I) {
64        let head = self.left_head.map_or(0, |x| x + 1);
65        assert!(head < self.right_head);
66        self.stacks[head] = value;
67        self.left_head = Some(head);
68    }
69
70    /// Push a value on the right stack
71    pub fn push_right(&mut self, value: I) {
72        self.right_head -= 1;
73        if let Some(left_head) = self.left_head {
74            assert!(self.right_head > left_head);
75        }
76        self.stacks[self.right_head] = value;
77    }
78
79    /// Pop a value from the left stack
80    pub fn pop_left(&mut self) -> Option<I> {
81        match self.left_head {
82            Some(left_head) => {
83                let res = self.stacks[left_head].clone();
84                self.left_head = if left_head > 0 {
85                    Some(left_head - 1)
86                } else {
87                    None
88                };
89                Some(res)
90            }
91            None => None,
92        }
93    }
94
95    /// Pop a value from the right stack
96    pub fn pop_right(&mut self) -> Option<I> {
97        if self.right_head >= self.stacks.len() {
98            None
99        } else {
100            let res = self.stacks[self.right_head].clone();
101            self.right_head += 1;
102            Some(res)
103        }
104    }
105
106    /// Number of right elements this double stack contains
107    pub fn len_right(&self) -> usize {
108        let n = self.stacks.len();
109        n - self.right_head
110    }
111
112    /// Clear the right stack
113    pub fn clear_right(&mut self) {
114        self.right_head = self.stacks.len();
115    }
116
117    /// Clear the left stack
118    pub fn clear_left(&mut self) {
119        self.left_head = None;
120    }
121
122    /// Iterates along the right stack without removing items
123    pub fn iter_right(&self) -> slice::Iter<'_, I> {
124        self.stacks[self.right_head..].iter()
125    }
126
127    /// Push the values of the left stack onto the right stack.
128    pub fn push_left_on_right(&mut self) {
129        while let Some(val) = self.pop_left() {
130            self.push_right(val);
131        }
132    }
133
134    /// Push the values of the right stack onto the left stack.
135    pub fn push_right_on_left(&mut self) {
136        while let Some(val) = self.pop_right() {
137            self.push_left(val);
138        }
139    }
140}
141
142/// Enable extraction of stack val from iterators
143pub fn extract_stack_val<I>(stack_val: &StackVal<I>) -> &I {
144    match stack_val {
145        StackVal::Enter(i) | StackVal::Exit(i) => i,
146    }
147}
148
149#[cfg(test)]
150mod test {
151    use super::*;
152
153    #[test]
154    fn test_stack_val_default() {
155        let val = StackVal::<usize>::default();
156        assert_eq!(val, StackVal::<usize>::Enter(0));
157    }
158
159    // Testing with_capacity function
160    #[test]
161    #[should_panic]
162    fn test_create_stack_with_not_enough_capacity() {
163        let _stack = DStack::<i32>::with_capacity(1);
164    }
165
166    #[test]
167    fn test_create_empty_stack() {
168        const CAPACITY: usize = 10;
169        let stack = DStack::<i32>::with_capacity(CAPACITY);
170        assert_eq!(stack.stacks.len(), CAPACITY);
171        assert_eq!(stack.left_head, None);
172        assert_eq!(stack.right_head, CAPACITY);
173    }
174
175    // Testing capacity function
176    #[test]
177    fn test_capacity() {
178        const CAPACITY: usize = 10;
179        let stack = DStack::<i32>::with_capacity(CAPACITY);
180        assert_eq!(stack.capacity(), CAPACITY);
181    }
182
183    // Testing is_left_empty function
184    #[test]
185    fn test_is_left_empty_with_empty_stack() {
186        let stack = DStack::<i32>::with_capacity(10);
187        assert!(stack.is_left_empty());
188    }
189
190    #[test]
191    fn test_is_left_empty_with_non_empty_stack() {
192        let mut stack = DStack::<i32>::with_capacity(10);
193        stack.push_left(3);
194        assert!(!stack.is_left_empty());
195    }
196
197    #[test]
198    fn test_is_left_empty_with_right_non_empty_stack() {
199        let mut stack = DStack::<i32>::with_capacity(10);
200        stack.push_right(3);
201        assert!(stack.is_left_empty());
202    }
203
204    // Testing is_right_empty function
205    #[test]
206    fn test_is_right_empty_with_empty_stack() {
207        let stack = DStack::<i32>::with_capacity(10);
208        assert!(stack.is_right_empty());
209    }
210
211    #[test]
212    fn test_is_right_empty_with_non_empty_stack() {
213        let mut stack = DStack::with_capacity(10);
214        stack.push_right(3);
215        assert!(!stack.is_right_empty());
216    }
217
218    #[test]
219    fn test_is_right_empty_with_left_non_empty_stack() {
220        let mut stack = DStack::with_capacity(10);
221        stack.push_left(3);
222        assert!(stack.is_right_empty());
223    }
224
225    // Testing push_left function
226    #[test]
227    fn test_push_left_stack() {
228        let mut stack = DStack::with_capacity(3);
229        stack.push_left(1);
230        stack.push_left(2);
231        stack.push_left(3);
232        assert_eq!(stack.stacks[0], 1);
233        assert_eq!(stack.stacks[1], 2);
234        assert_eq!(stack.stacks[2], 3);
235        assert_eq!(stack.left_head, Some(2));
236        assert_eq!(stack.right_head, 3);
237    }
238
239    #[test]
240    #[should_panic]
241    fn test_push_left_more_item_that_capacity_stack() {
242        let mut stack = DStack::with_capacity(2);
243        stack.push_left(1);
244        stack.push_left(2);
245        stack.push_left(3);
246    }
247
248    // Testing push_right function
249    #[test]
250    fn test_push_right_stack() {
251        let mut stack = DStack::with_capacity(3);
252        stack.push_right(1);
253        stack.push_right(2);
254        stack.push_right(3);
255        assert_eq!(stack.stacks[0], 3);
256        assert_eq!(stack.stacks[1], 2);
257        assert_eq!(stack.stacks[2], 1);
258        assert_eq!(stack.right_head, 0);
259        assert_eq!(stack.left_head, None);
260    }
261
262    #[test]
263    #[should_panic]
264    fn test_push_right_more_item_that_capacity_stack() {
265        let mut stack = DStack::with_capacity(2);
266        stack.push_right(1);
267        stack.push_right(2);
268        stack.push_right(3);
269    }
270
271    // Testing push_left and push_right functions
272    #[test]
273    fn test_push_left_without_exceeding_right_head_stack() {
274        let mut stack = DStack::with_capacity(3);
275        stack.push_left(1);
276        stack.push_right(3);
277        stack.push_left(2);
278        assert_eq!(stack.stacks[0], 1);
279        assert_eq!(stack.stacks[1], 2);
280        assert_eq!(stack.stacks[2], 3);
281        assert_eq!(stack.left_head, Some(1));
282        assert_eq!(stack.right_head, 2);
283    }
284
285    #[test]
286    #[should_panic]
287    fn test_push_left_exceeding_right_head_stack() {
288        let mut stack = DStack::with_capacity(3);
289        stack.push_right(3);
290        stack.push_left(1);
291        stack.push_right(2);
292        stack.push_left(10);
293    }
294
295    #[test]
296    fn test_push_right_without_exceeding_left_head_stack() {
297        let mut stack = DStack::with_capacity(3);
298        stack.push_right(3);
299        stack.push_left(1);
300        stack.push_right(2);
301        assert_eq!(stack.stacks[0], 1);
302        assert_eq!(stack.stacks[1], 2);
303        assert_eq!(stack.stacks[2], 3);
304        assert_eq!(stack.left_head, Some(0));
305        assert_eq!(stack.right_head, 1);
306    }
307
308    #[test]
309    #[should_panic]
310    fn test_push_right_exceeding_left_head_stack() {
311        let mut stack = DStack::with_capacity(3);
312        stack.push_left(3);
313        stack.push_right(1);
314        stack.push_left(2);
315        stack.push_right(10);
316    }
317
318    // Testing pop_left
319    #[test]
320    fn test_pop_left_on_empty_stack() {
321        let mut stack = DStack::<i32>::with_capacity(10);
322        let res = stack.pop_left();
323        assert!(matches!(res, None));
324        assert_eq!(stack.left_head, None);
325        assert_eq!(stack.right_head, 10);
326    }
327
328    #[test]
329    fn test_pop_left_on_non_empty_stack() {
330        let mut stack = DStack::with_capacity(10);
331        stack.push_left(144);
332        let res = stack.pop_left();
333        assert_eq!(res, Some(144));
334        assert_eq!(stack.left_head, None);
335        assert_eq!(stack.right_head, 10);
336    }
337
338    // Testing pop_right
339    #[test]
340    fn test_pop_right_on_empty_stack() {
341        let mut stack = DStack::<i32>::with_capacity(10);
342        let res = stack.pop_right();
343        assert!(matches!(res, None));
344        assert_eq!(stack.left_head, None);
345        assert_eq!(stack.right_head, 10);
346    }
347
348    #[test]
349    fn test_pop_right_on_non_empty_stack() {
350        let mut stack = DStack::with_capacity(10);
351        stack.push_right(144);
352        let res = stack.pop_right();
353        assert_eq!(res, Some(144));
354        assert_eq!(stack.left_head, None);
355        assert_eq!(stack.right_head, 10);
356    }
357
358    // Testing len_right function
359    #[test]
360    fn test_len_right_on_empty_stack() {
361        let stack = DStack::<i32>::with_capacity(10);
362        assert_eq!(stack.len_right(), 0);
363    }
364
365    #[test]
366    fn test_len_right_on_full_stack() {
367        let mut stack = DStack::<i32>::with_capacity(3);
368        stack.push_right(1);
369        stack.push_right(2);
370        stack.push_left(3);
371        assert_eq!(stack.len_right(), 2);
372    }
373
374    // Testing clear_right function
375    #[test]
376    fn test_clear_right_on_empty_stack() {
377        let mut stack = DStack::<i32>::with_capacity(10);
378        stack.clear_right();
379        assert_eq!(stack.right_head, 10);
380        assert_eq!(stack.left_head, None);
381    }
382
383    #[test]
384    fn test_clear_right_on_full_stack() {
385        let mut stack = DStack::<i32>::with_capacity(3);
386        stack.push_right(1);
387        stack.push_right(2);
388        stack.push_left(3);
389        stack.clear_right();
390        assert_eq!(stack.right_head, 3);
391        assert_eq!(stack.left_head, Some(0));
392    }
393
394    // Testing clear_left function
395    #[test]
396    fn test_clear_left_on_empty_stack() {
397        let mut stack = DStack::<i32>::with_capacity(10);
398        stack.clear_left();
399        assert_eq!(stack.right_head, 10);
400        assert_eq!(stack.left_head, None);
401    }
402
403    #[test]
404    fn test_clear_left_on_full_stack() {
405        let mut stack = DStack::<i32>::with_capacity(3);
406        stack.push_left(1);
407        stack.push_left(2);
408        stack.push_right(3);
409        stack.clear_left();
410        assert_eq!(stack.right_head, 2);
411        assert_eq!(stack.left_head, None);
412    }
413
414    // Testing iter_right function
415    #[test]
416    fn test_iter_right_on_empty_stack() {
417        let stack = DStack::<i32>::with_capacity(3);
418        let mut it = stack.iter_right();
419        assert_eq!(it.next(), None);
420    }
421
422    #[test]
423    fn test_iter_right_on_full_stack() {
424        let mut stack = DStack::<i32>::with_capacity(3);
425        stack.push_left(1);
426        stack.push_left(2);
427        stack.push_right(3);
428        let mut it = stack.iter_right();
429        assert!(matches!(it.next(), Some(3)));
430        assert_eq!(it.next(), None);
431    }
432
433    // Testing push_left_on_right function
434    #[test]
435    fn test_push_left_on_right_with_empty_stack() {
436        let mut stack = DStack::<i32>::with_capacity(10);
437        stack.push_left_on_right();
438        assert_eq!(stack.left_head, None);
439        assert_eq!(stack.right_head, 10);
440    }
441
442    #[test]
443    fn test_push_left_on_right_stack() {
444        let mut stack = DStack::with_capacity(10);
445        stack.push_left(1);
446        stack.push_left(2);
447        stack.push_left(3);
448        stack.push_left_on_right();
449        assert_eq!(stack.left_head, None);
450        assert_eq!(stack.right_head, 7);
451    }
452
453    // Testing push_right_on_left function
454    #[test]
455    fn test_push_right_on_left_with_empty_stack() {
456        let mut stack = DStack::<i32>::with_capacity(10);
457        stack.push_right_on_left();
458        assert_eq!(stack.left_head, None);
459        assert_eq!(stack.right_head, 10);
460    }
461
462    #[test]
463    fn test_push_right_on_left_stack() {
464        let mut stack = DStack::with_capacity(10);
465        stack.push_right(1);
466        stack.push_right(2);
467        stack.push_right(3);
468        stack.push_right_on_left();
469        assert_eq!(stack.left_head, Some(2));
470        assert_eq!(stack.right_head, 10);
471    }
472}