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
use std::collections::HashSet;

use nandoize::PersistableDerive;
use object_lib::Persistable;

/*
#[derive(PersistableDerive)]
pub struct Set {
    pub data: HashSet<i64>,
}

#[nandoize]
pub fn get_difference(some_set: &Set, some_other_set: &Set, output_set: &mut Set) -> () {
    output_set.data = some_set
        .data
        .difference(&some_other_set.data)
        .cloned()
        .collect();
}

#[nandoize]
pub fn get_symmetric_difference(some_set: &Set, some_other_set: &Set, output_set: &mut Set) -> () {
    output_set.data = some_set
        .data
        .symmetric_difference(&some_other_set.data)
        .cloned()
        .collect();
}

#[nandoize]
pub fn read_set(some_set: &Set) -> () {
    print!("Contents: {{");
    for e in &some_set.data {
        print!("{e}, ")
    }
    println!("}}");
}
*/

const SLOW_SET_N_ELEMS: usize = 1024;

#[repr(C)]
#[derive(PersistableDerive)]
pub struct SlowSet {
    current_idx: usize,
    pub data: [usize; SLOW_SET_N_ELEMS],
}

impl Default for SlowSet {
    fn default() -> Self {
        Self {
            current_idx: 0,
            data: [0; SLOW_SET_N_ELEMS],
        }
    }
}

impl SlowSet {
    #[allow(dead_code)]
    fn as_set(&self) -> HashSet<usize> {
        self.data.into()
    }

    pub fn insert(&mut self, elem: usize) {
        self.data[self.current_idx] = elem;
        self.current_idx += 1;
    }

    pub fn sort(&mut self) {
        self.data.sort();
    }

    pub fn get_difference(&self, other: &Self) -> Self {
        let mut res_data = Self::default();

        let mut last_visited_idx = 0;
        for e in self.data {
            let mut should_insert = true;
            while last_visited_idx < other.current_idx {
                should_insert = false;
                if e > other.data[last_visited_idx] {
                    last_visited_idx += 1;
                } else if e == other.data[last_visited_idx] {
                    break;
                } else {
                    res_data.insert(e);
                    break;
                }
            }

            if should_insert {
                res_data.insert(e);
            }
        }

        res_data
    }
}

// #[nandoize]
pub fn get_difference_slow_set(
    some_set: &SlowSet,
    some_other_set: &SlowSet,
    output_set: &mut SlowSet,
) -> () {
    *output_set = some_set.get_difference(&some_other_set);
}

// #[nandoize]
pub fn read_slow_set(set: &SlowSet) -> () {
    print!("Contents: {{");
    for e in &set.data[0..set.data.len()] {
        print!("{e}, ")
    }
    println!("}}");
}