Skip to main content

bigfixed/big_fixed/
index_ops.rs

1use crate::{digit::*, Index as Indx, BigFixed};
2
3use std::{ops::{Index, IndexMut}};
4
5impl Index<Indx> for BigFixed {
6    type Output = Digit;
7    fn index(&self, position: Indx) -> &Digit {
8        assert!(self.properly_positioned(), "indexing into an impoperly positioned BigFixed");
9        match position {
10            Indx::Position(_) => {
11                let shifted = (position - self.position).unwrap();
12                if shifted >= self.body.len() as isize {
13                    &self.head
14                } else if shifted >= 0isize {
15                    &self.body[usize::from(shifted)]
16                } else {
17                    &0
18                }
19            },
20            Indx::Bit(b) => {
21                let d = self[Indx::bit_to_position(b)];
22                if (d >> position.bit_position_excess()) & 1 == 1 {
23                    &1
24                } else {
25                    &0
26                }
27            }
28        }
29    }
30}
31
32impl Index<isize> for BigFixed {
33    type Output = Digit;
34    fn index(&self, position: isize) -> &Digit {
35        &self[Indx::Position(position)]
36    }
37}
38
39// Gives a reference to the digit in the corresponding position regardless of Index type (Bit/Position). Use set_bit for bit-level mutation.
40impl IndexMut<Indx> for BigFixed {
41    fn index_mut(&mut self, position: Indx) -> &mut Digit {
42        let position = position.cast_to_position();
43        self.ensure_valid_position(position).unwrap(); // includes a call to self.fix_position();
44        self.body.index_mut(usize::from((position - self.position).unwrap()))
45    }
46}
47
48impl IndexMut<isize> for BigFixed {
49    fn index_mut(&mut self, position: isize) -> &mut Digit {
50        self.index_mut(Indx::Position(position))
51    }
52}
53
54impl BigFixed {
55    pub fn set_bit(&mut self, index: isize, value: Digit) {
56        assert!(value == 0 || value == 1, "set_bit requires a bit (0 or 1)");
57        let position = Indx::Bit(index);
58        let shift = Indx::bit_position_excess(&position);
59        self[position] = (self[position.cast_to_position()] & !(1 << shift)) | (value << shift);
60    }
61}