weavatrix_graph/matrix/
dense.rs1use crate::Vec;
2use crate::{GraphError, NodeIndex, Result};
3use serde::{Deserialize, Deserializer, Serialize, de::Error as _};
4
5#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
6pub struct DenseMatrix<T> {
7 node_count: u32,
8 edge_count: usize,
9 cells: Vec<Option<T>>,
10}
11
12impl<T> DenseMatrix<T> {
13 pub fn try_new(node_count: usize) -> Result<Self> {
19 let compact = u32::try_from(node_count).map_err(|_| GraphError::IndexCapacityExceeded {
20 category: "matrix nodes",
21 count: node_count,
22 })?;
23 let cells = node_count
24 .checked_mul(node_count)
25 .ok_or(GraphError::ArithmeticOverflow {
26 operation: "dense matrix dimensions",
27 })?;
28 Ok(Self {
29 node_count: compact,
30 edge_count: 0,
31 cells: core::iter::repeat_with(|| None).take(cells).collect(),
32 })
33 }
34
35 #[must_use]
36 pub const fn node_count(&self) -> usize {
37 self.node_count as usize
38 }
39
40 #[must_use]
41 pub const fn edge_count(&self) -> usize {
42 self.edge_count
43 }
44
45 #[must_use]
46 pub fn get(&self, source: NodeIndex, target: NodeIndex) -> Option<&T> {
47 self.slot(source, target)
48 .ok()
49 .and_then(|slot| self.cells[slot].as_ref())
50 }
51
52 #[must_use]
53 pub fn get_mut(&mut self, source: NodeIndex, target: NodeIndex) -> Option<&mut T> {
54 self.slot(source, target)
55 .ok()
56 .and_then(|slot| self.cells[slot].as_mut())
57 }
58
59 pub fn insert(&mut self, source: NodeIndex, target: NodeIndex, value: T) -> Result<Option<T>> {
65 let slot = self.slot(source, target)?;
66 let previous = self.cells[slot].replace(value);
67 self.edge_count += usize::from(previous.is_none());
68 Ok(previous)
69 }
70
71 pub fn remove(&mut self, source: NodeIndex, target: NodeIndex) -> Option<T> {
72 let slot = self.slot(source, target).ok()?;
73 let previous = self.cells[slot].take();
74 self.edge_count -= usize::from(previous.is_some());
75 previous
76 }
77
78 pub fn outgoing(&self, source: NodeIndex) -> impl Iterator<Item = (NodeIndex, &T)> {
79 let valid = source.index() < self.node_count();
80 (0..self.node_count()).filter_map(move |target| {
81 let target = NodeIndex::new(u32::try_from(target).ok()?);
82 valid
83 .then(|| self.get(source, target))
84 .flatten()
85 .map(|value| (target, value))
86 })
87 }
88
89 pub fn incoming(&self, target: NodeIndex) -> impl Iterator<Item = (NodeIndex, &T)> {
90 let valid = target.index() < self.node_count();
91 (0..self.node_count()).filter_map(move |source| {
92 let source = NodeIndex::new(u32::try_from(source).ok()?);
93 valid
94 .then(|| self.get(source, target))
95 .flatten()
96 .map(|value| (source, value))
97 })
98 }
99
100 pub fn edges(&self) -> impl Iterator<Item = (NodeIndex, NodeIndex, &T)> {
101 self.cells.iter().enumerate().filter_map(|(slot, value)| {
102 let value = value.as_ref()?;
103 let source = u32::try_from(slot / self.node_count()).ok()?;
104 let target = u32::try_from(slot % self.node_count()).ok()?;
105 Some((NodeIndex::new(source), NodeIndex::new(target), value))
106 })
107 }
108
109 fn slot(&self, source: NodeIndex, target: NodeIndex) -> Result<usize> {
110 let count = self.node_count();
111 if source.index() >= count {
112 return Err(GraphError::InvalidNodeIndex {
113 node: source.index(),
114 node_count: count,
115 });
116 }
117 if target.index() >= count {
118 return Err(GraphError::InvalidNodeIndex {
119 node: target.index(),
120 node_count: count,
121 });
122 }
123 Ok(source.index() * count + target.index())
124 }
125}
126
127impl<T: Clone> DenseMatrix<T> {
128 pub fn insert_undirected(
134 &mut self,
135 left: NodeIndex,
136 right: NodeIndex,
137 value: T,
138 ) -> Result<(Option<T>, Option<T>)> {
139 let reverse = value.clone();
140 let first = self.insert(left, right, value)?;
141 let second = if left == right {
142 first.clone()
143 } else {
144 self.insert(right, left, reverse)?
145 };
146 Ok((first, second))
147 }
148}
149
150#[derive(Deserialize)]
151struct DenseWire<T> {
152 node_count: u32,
153 #[serde(rename = "edge_count")]
154 _edge_count: usize,
155 cells: Vec<Option<T>>,
156}
157
158impl<'de, T> Deserialize<'de> for DenseMatrix<T>
159where
160 T: Deserialize<'de>,
161{
162 fn deserialize<D>(deserializer: D) -> core::result::Result<Self, D::Error>
163 where
164 D: Deserializer<'de>,
165 {
166 let wire = DenseWire::deserialize(deserializer)?;
167 let node_count = wire.node_count as usize;
168 let expected = node_count
169 .checked_mul(node_count)
170 .ok_or_else(|| D::Error::custom("dense matrix dimensions overflow"))?;
171 if wire.cells.len() != expected {
172 return Err(D::Error::custom(format!(
173 "dense matrix has {} cells, expected {expected}",
174 wire.cells.len()
175 )));
176 }
177 let edge_count = wire.cells.iter().filter(|cell| cell.is_some()).count();
178 Ok(Self {
179 node_count: wire.node_count,
180 edge_count,
181 cells: wire.cells,
182 })
183 }
184}