1use big_int_proc::BigIntTraits;
18use std::collections::VecDeque;
19
20use crate::prelude::*;
21
22mod tests;
23
24pub type Datum = u8;
29
30pub const DATUM_SIZE: usize = std::mem::size_of::<Datum>() * 8;
32
33pub type DenormalTight<const BASE: usize> = Denormal<BASE, Tight<BASE>>;
35
36#[derive(Debug, Clone, BigIntTraits)]
52pub struct Tight<const BASE: usize> {
53 sign: Sign,
54 data: VecDeque<Datum>,
55 start_offset: usize,
56 end_offset: usize,
57}
58
59impl<const BASE: usize> Tight<BASE> {
60
61 pub unsafe fn from_raw_parts(
79 data: VecDeque<Datum>,
80 start_offset: usize,
81 end_offset: usize,
82 ) -> Self {
83 Self {
84 sign: Positive,
85 data,
86 start_offset,
87 end_offset,
88 }
89 }
90
91 pub fn aligned(mut self) -> Self {
109 let empty_cells = self.start_offset / DATUM_SIZE;
110 self.start_offset -= empty_cells * DATUM_SIZE;
111 self.end_offset -= empty_cells * DATUM_SIZE;
112 let data_cells = self.data.into_iter().skip(empty_cells);
113 self.data = if self.start_offset == 0 {
114 data_cells.collect()
115 } else {
116 let data_length = (self.end_offset - self.start_offset).div_ceil(DATUM_SIZE);
117 let mut data = VecDeque::new();
118 let left_half_offset = DATUM_SIZE - self.start_offset;
119 let left_half_mask = mask!(self.start_offset) << left_half_offset;
120 let right_half_mask = mask!(DATUM_SIZE - self.start_offset);
121 let mut right_half = None;
122 for datum in data_cells {
123 if let Some(right_half) = right_half {
124 let left_half = (datum & left_half_mask) >> left_half_offset;
125 let aligned_datum = left_half | right_half;
126 data.push_back(aligned_datum);
127 if data.len() >= data_length {
128 break;
129 }
130 }
131 right_half = Some((datum & right_half_mask) << self.start_offset);
132 }
133 if let Some(right_half) = right_half {
134 if data.len() < data_length {
135 data.push_back(right_half);
136 }
137 }
138 self.end_offset -= self.start_offset;
139 self.start_offset = 0;
140 data
141 };
142 self
143 }
144}
145
146impl<const BASE: usize> BigInt<{ BASE }> for Tight<BASE> {
147 type Builder = TightBuilder<{ BASE }>;
148 type Denormal = Denormal<BASE, Self>;
149
150 fn len(&self) -> usize {
151 (self.end_offset - self.start_offset) / Self::BITS_PER_DIGIT
152 }
153
154 fn get_digit(&self, digit: usize) -> Option<Digit> {
155 let mut digit_offset = self.start_offset + digit * Self::BITS_PER_DIGIT;
156 if digit_offset >= self.end_offset {
157 None
158 } else {
159 let mut digit_value = 0;
160 let mut bits_left_to_pull = Self::BITS_PER_DIGIT;
161 while bits_left_to_pull > 0 {
162 let datum_index = digit_offset / DATUM_SIZE;
163 let bit_in_datum = digit_offset % DATUM_SIZE;
164 let bits_available_in_datum = DATUM_SIZE - bit_in_datum;
165 let bits_to_take = bits_available_in_datum.min(bits_left_to_pull);
166 digit_offset += bits_to_take;
167 bits_left_to_pull -= bits_to_take;
168 let datum_offset = bits_available_in_datum - bits_to_take;
169 let datum_mask: Datum = mask!(bits_to_take) << datum_offset;
170 let piece_of_digit = ((self.data[datum_index] & datum_mask) as Digit
171 >> datum_offset)
172 << bits_left_to_pull;
173 digit_value |= piece_of_digit;
174 }
175 Some(digit_value)
176 }
177 }
178
179 fn set_digit(&mut self, digit: usize, value: Digit) {
180 let mut digit_offset = self.start_offset + digit * Self::BITS_PER_DIGIT;
181 if digit_offset < self.end_offset {
182 let mut bits_left_to_set = Self::BITS_PER_DIGIT;
183 while bits_left_to_set > 0 {
184 let datum_index = digit_offset / DATUM_SIZE;
185 let bit_in_datum = digit_offset % DATUM_SIZE;
186 let bits_left_in_datum = DATUM_SIZE - bit_in_datum;
187 let bits_to_set = bits_left_in_datum.min(bits_left_to_set);
188 digit_offset += bits_to_set;
189 bits_left_to_set -= bits_to_set;
190 let datum_offset = bits_left_in_datum - bits_to_set;
191 let piece_mask = mask!(bits_to_set) << bits_left_to_set;
192 let piece_of_digit = ((value & piece_mask) >> bits_left_to_set) << datum_offset;
193 let datum_mask = mask!(bits_to_set) << datum_offset;
194 self.data[datum_index] &= !datum_mask;
195 self.data[datum_index] |= piece_of_digit as Datum;
196 }
197 }
198 }
199
200 fn zero() -> Self {
201 Self {
202 sign: Positive,
203 data: VecDeque::from(vec![0; Self::BITS_PER_DIGIT.div_ceil(DATUM_SIZE)]),
204 start_offset: 0,
205 end_offset: Self::BITS_PER_DIGIT,
206 }
207 }
208
209 fn sign(&self) -> Sign {
210 self.sign
211 }
212
213 fn with_sign(self, sign: Sign) -> Self {
214 Self { sign, ..self }
215 }
216
217 fn set_sign(&mut self, sign: Sign) {
218 self.sign = sign;
219 }
220
221 fn push_back(&mut self, digit: Digit) {
222 let mut bits_left_to_set = Self::BITS_PER_DIGIT;
223 while bits_left_to_set > 0 {
224 let datum_index = self.end_offset / DATUM_SIZE;
225 if datum_index >= self.data.len() {
226 self.data.push_back(0);
227 }
228 let bit_in_datum = self.end_offset % DATUM_SIZE;
229 let space_left_in_datum = DATUM_SIZE - bit_in_datum;
230 let bits_to_take = space_left_in_datum.min(bits_left_to_set);
231 self.end_offset += bits_to_take;
232 bits_left_to_set -= bits_to_take;
233 let digit_mask = mask!(bits_to_take) << bits_left_to_set;
234 let piece_of_digit = (((digit_mask & digit) >> bits_left_to_set)
235 << (DATUM_SIZE - bits_to_take))
236 >> bit_in_datum;
237 self.data[datum_index] |= piece_of_digit as Datum;
238 }
239 }
240
241 unsafe fn push_front(&mut self, digit: Digit) {
242 let mut bits_left_to_set = Self::BITS_PER_DIGIT;
243 while bits_left_to_set > 0 {
244 if self.start_offset == 0 {
245 self.data.push_front(0);
246 self.start_offset += DATUM_SIZE;
247 self.end_offset += DATUM_SIZE;
248 }
249 let datum_index = (self.start_offset - 1) / DATUM_SIZE;
250 let space_left_in_datum = (self.start_offset - 1) % DATUM_SIZE + 1;
251 let bits_to_take = space_left_in_datum.min(bits_left_to_set);
252 self.start_offset -= bits_to_take;
253 let mask_offset = Self::BITS_PER_DIGIT - bits_left_to_set;
254 let digit_mask = mask!(bits_to_take) << mask_offset;
255 bits_left_to_set -= bits_to_take;
256 let piece_of_digit =
257 ((digit_mask & digit) >> mask_offset) << (DATUM_SIZE - space_left_in_datum);
258 self.data[datum_index] |= piece_of_digit as Datum;
259 }
260 }
261
262 unsafe fn shr_assign_inner(&mut self, amount: usize) {
263 self.end_offset = self
264 .end_offset
265 .checked_sub(amount * Self::BITS_PER_DIGIT)
266 .unwrap_or_default()
267 .max(self.start_offset);
268 self.normalize();
269 }
270
271 unsafe fn shl_assign_inner(&mut self, amount: usize) {
272 self.end_offset += Self::BITS_PER_DIGIT * amount;
273 let new_len = self.end_offset.div_ceil(DATUM_SIZE);
274 let cur_len = self.data.len();
275 self.data.extend(vec![0; new_len - cur_len]);
276 }
277
278 fn normalized(mut self) -> Self {
282 while self.start_offset < self.end_offset && self.get_digit(0) == Some(0) {
283 self.start_offset += Self::BITS_PER_DIGIT;
284 }
285 if self.start_offset >= self.end_offset {
286 Self::zero()
287 } else if self.start_offset > 0 {
288 self.aligned()
289 } else {
290 if self.data.len() * DATUM_SIZE >= self.end_offset + DATUM_SIZE {
291 self.data = self
292 .data
293 .into_iter()
294 .take(self.end_offset.div_ceil(DATUM_SIZE))
295 .collect();
296 }
297 self
298 }
299 }
300
301 unsafe fn pop_front(&mut self) -> Option<Digit> {
302 let digit = self.get_digit(0);
303 if digit.is_some() {
304 self.start_offset += Self::BITS_PER_DIGIT;
305 if self.start_offset >= DATUM_SIZE {
306 let new_start_offset = self.start_offset % DATUM_SIZE;
307 let offset_shift = self.start_offset - new_start_offset;
308 for _ in 0..self.start_offset / DATUM_SIZE {
309 self.data.pop_front();
310 }
311 self.start_offset = new_start_offset;
312 self.end_offset -= offset_shift;
313 }
314 }
315 digit
316 }
317
318 unsafe fn pop_back(&mut self) -> Option<Digit> {
319 let digit = self.get_back(1);
320 if digit.is_some() {
321 self.end_offset = self
322 .end_offset
323 .checked_sub(Self::BITS_PER_DIGIT)
324 .unwrap_or_default()
325 .max(self.start_offset);
326 for _ in 0..self.data.len() - self.end_offset.div_ceil(DATUM_SIZE) {
327 self.data.pop_back();
328 }
329 }
330 digit
331 }
332}
333
334#[derive(Debug)]
351pub struct TightBuilder<const BASE: usize>(Tight<BASE>);
352
353impl<const BASE: usize> BigIntBuilder<BASE> for TightBuilder<BASE> {
354 fn new() -> Self {
355 Self(Tight {
356 sign: Positive,
357 data: VecDeque::new(),
358 start_offset: 0,
359 end_offset: 0,
360 })
361 }
362
363 fn push_front(&mut self, digit: Digit) {
364 unsafe { self.0.push_front(digit) };
365 }
366
367 fn push_back(&mut self, digit: Digit) {
368 self.0.push_back(digit);
369 }
370
371 fn is_empty(&self) -> bool {
372 self.0.start_offset >= self.0.end_offset
373 }
374
375 fn with_sign(self, sign: Sign) -> Self {
376 Self(self.0.with_sign(sign))
377 }
378}
379
380impl<const BASE: usize> From<TightBuilder<BASE>> for Denormal<BASE, Tight<BASE>> {
381 fn from(value: TightBuilder<BASE>) -> Self {
382 Denormal(value.0)
383 }
384}
385
386impl<const BASE: usize> From<TightBuilder<BASE>> for Tight<BASE> {
387 fn from(value: TightBuilder<BASE>) -> Self {
388 let denormal: <Self as BigInt<BASE>>::Denormal = value.into();
389 denormal.unwrap()
390 }
391}