Skip to main content

apple_quant_algorithmic/binned_method/
fixed.rs

1use std::{array, collections::BTreeMap};
2
3use smallvec::SmallVec;
4
5use crate::binned_method::{BinnedDataError, FixedSectorDef};
6
7/// Fixed collection of data binned by an index.
8pub struct FixedBinnedData<T: Clone, const SECTOR_DATA_COUNT: usize> {
9	sectors: BTreeMap<u64, [Option<T>; SECTOR_DATA_COUNT]>,
10	last_sector_def: Option<FixedSectorDef>,
11}
12
13impl<T: Clone, const SECTOR_DATA_COUNT: usize> FixedBinnedData<T, SECTOR_DATA_COUNT> {
14	pub fn last_sector_def(&self) -> &Option<FixedSectorDef> {
15		&self.last_sector_def
16	}
17
18	pub fn remove_last(&mut self) -> Result<Option<T>, BinnedDataError> {
19		let Some(last_sector_def) = self.last_sector_def else {
20			return Ok(None);
21		};
22
23		let sector = self.get_sector_mut(last_sector_def.sector_idx)?;
24
25		#[cfg(debug_assertions)]
26		if last_sector_def.data_idx >= SECTOR_DATA_COUNT {
27			return Err(
28				BinnedDataError::SectorDataOutOfRange {
29					data_index: last_sector_def.data_idx,
30					sector_data_count: SECTOR_DATA_COUNT,
31				},
32			);
33		}
34
35		let Some(data) = sector[last_sector_def.data_idx].take() else {
36			return Err(BinnedDataError::InternalError);
37		};
38
39		if last_sector_def.data_idx == 0 {
40			if last_sector_def.sector_idx == 0 {
41				self.last_sector_def = None;
42				self.sectors
43					.remove(&last_sector_def.sector_idx);
44				return Ok(Some(data));
45			}
46
47			if self
48				.get_sector(last_sector_def.sector_idx - 1)
49				.is_err()
50			{
51				self.last_sector_def = None;
52				self.sectors
53					.remove(&last_sector_def.sector_idx);
54				return Ok(Some(data));
55			}
56
57			self.last_sector_def = Some(FixedSectorDef {
58				sector_idx: last_sector_def.sector_idx - 1,
59				data_idx: SECTOR_DATA_COUNT - 1,
60			});
61			self.sectors
62				.remove(&last_sector_def.sector_idx);
63
64			return Ok(Some(data));
65		}
66
67		self.last_sector_def = Some(FixedSectorDef {
68			sector_idx: last_sector_def.sector_idx,
69			data_idx: last_sector_def.data_idx - 1,
70		});
71
72		Ok(Some(data))
73	}
74
75	pub fn append(
76		&mut self,
77		first_sector_idx: u64,
78		data: impl IntoIterator<Item = T>,
79	) -> Result<(), ()> {
80		let data = data.into_iter();
81
82		let mut appending_sector_def = self
83			.last_sector_def
84			.unwrap_or(FixedSectorDef {
85				sector_idx: first_sector_idx / SECTOR_DATA_COUNT as u64,
86				data_idx: (first_sector_idx
87					- ((first_sector_idx / SECTOR_DATA_COUNT as u64) * SECTOR_DATA_COUNT as u64))
88					as usize,
89			});
90
91		let mut sector = match self.get_sector_mut(appending_sector_def.sector_idx) {
92			Ok(sector) => sector,
93			Err(BinnedDataError::InvalidSector { sector_idx: _ }) => {
94				self.sectors.insert(
95					appending_sector_def.sector_idx,
96					array::from_fn(|_| None),
97				);
98
99				let Ok(sector) = self.get_sector_mut(appending_sector_def.sector_idx) else {
100					return Err(());
101				};
102
103				sector
104			}
105			Err(_) => unimplemented!(),
106		};
107
108		for next_data in data {
109			appending_sector_def.data_idx += 1;
110
111			if appending_sector_def.data_idx == SECTOR_DATA_COUNT {
112				appending_sector_def.data_idx = 0;
113				appending_sector_def.sector_idx += 1;
114
115				self.sectors.insert(
116					appending_sector_def.sector_idx,
117					array::from_fn(|_| None),
118				);
119
120				let Ok(new_sector) = self.get_sector_mut(appending_sector_def.sector_idx) else {
121					return Err(());
122				};
123
124				sector = new_sector;
125			}
126
127			sector[appending_sector_def.data_idx] = Some(next_data);
128		}
129
130		Ok(())
131	}
132
133	pub fn get(
134		&mut self,
135		index: usize,
136	) -> Result<&Option<T>, BinnedDataError> {
137		let sector_id = index / SECTOR_DATA_COUNT;
138		let data_idx = index - (sector_id * SECTOR_DATA_COUNT);
139
140		let sector = self.get_sector_mut(sector_id as u64)?;
141		Ok(&sector[data_idx])
142	}
143
144	pub fn iter(
145		&mut self,
146		min_idx: usize,
147		max_idx: usize,
148	) -> Result<impl Iterator<Item = &Option<T>>, BinnedDataError> {
149		if max_idx < min_idx {
150			return Err(
151				BinnedDataError::InvalidMinMax {
152					min: min_idx as u64,
153					max: max_idx as u64,
154				},
155			);
156		}
157
158		let Some(last_sector_def) = &self.last_sector_def else {
159			return Err(BinnedDataError::InternalError);
160		};
161
162		let iter_len = max_idx - min_idx + 1;
163
164		let mut data = SmallVec::<[&Option<T>; 1024]>::with_capacity(iter_len);
165
166		let mut last_idx = min_idx;
167
168		loop {
169			let sector_id = last_idx / SECTOR_DATA_COUNT;
170			let data_min_idx = last_idx - (sector_id * SECTOR_DATA_COUNT);
171			let mut data_max_idx = (sector_id + 1) * SECTOR_DATA_COUNT - 1;
172			let sector_id = sector_id as u64;
173
174			let Ok(sector) = self.get_sector(sector_id) else {
175				break;
176			};
177
178			if last_sector_def.sector_idx == sector_id as u64 {
179				data_max_idx = last_sector_def.data_idx;
180			}
181
182			data.extend(
183				sector
184					.iter()
185					.take(data_max_idx + 1)
186					.skip(data_min_idx),
187			);
188
189			last_idx = data_max_idx + 1;
190		}
191
192		Ok(data.into_iter())
193	}
194
195	fn get_sector(
196		&self,
197		sector_idx: u64,
198	) -> Result<&[Option<T>; SECTOR_DATA_COUNT], BinnedDataError> {
199		if let Some(sector) = self.sectors.get(&sector_idx) {
200			return Ok(sector);
201		}
202
203		Err(BinnedDataError::InvalidSector { sector_idx })
204	}
205
206	fn get_sector_mut(
207		&mut self,
208		sector_idx: u64,
209	) -> Result<&mut [Option<T>; SECTOR_DATA_COUNT], BinnedDataError> {
210		if let Some(sector) = self
211			.sectors
212			.get_mut(&sector_idx)
213		{
214			return Ok(sector);
215		}
216
217		Err(BinnedDataError::InvalidSector { sector_idx })
218	}
219}
220
221impl<T: Clone, const SECTOR_DATA_COUNT: usize> Default for FixedBinnedData<T, SECTOR_DATA_COUNT> {
222	fn default() -> Self {
223		Self {
224			sectors: BTreeMap::default(),
225			last_sector_def: None,
226		}
227	}
228}