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
mod fp_fx;
mod fp_q;
use crate::UInt;
pub use fp_fx::{to_Fx, Fx};
pub use fp_q::{to_Q, Q};

pub trait FixedPoint {
    fn eval(&self) -> f64;
}

fn debug_print(val: UInt, m: i32, b: i32, is_exact: bool) -> String {
    const ANSI_RESET_COLOR: &str = "\x1b[0m";
    const ANSI_BLACK: &str = "\x1b[37;40m"; // bold, black background, white foreground
    const ANSI_MAGENTA: &str = "\x1b[45m"; // non bold, magenta background, black foreground

    let bits = format!("{:0width$b}", val, width = (b) as usize);

    let dots = if is_exact { "" } else { "..." };

    let ans = format!(
        "{ANSI_MAGENTA}{int}{ANSI_BLACK}{frac}{dots}{ANSI_RESET_COLOR}",
        int = &bits[..m as usize],
        frac = &bits[m as usize..],
    );

    ans
}

#[cfg(test)]
mod test {

    use crate::fixed_point::Q;

    #[test]
    fn test_add() {
        let fp1 = Q::new(0b1111, 3, 1, true);
        let fp2 = Q::new(0b1110, 3, 1, true);
        let fp3 = Q::new(0b11101, 4, 1, true);
        assert_eq!(fp1 + fp2, fp3);
    }

    #[test]
    fn test_sub() {
        let fp1 = Q::new(0b1111, 3, 1, true);
        let fp2 = Q::new(0b1110, 3, 1, true);
        let fp3 = Q::new(0b0001, 3, 1, true);
        assert_eq!(fp1 - fp2, fp3);
    }

    #[test]
    fn test_shift() {
        let fp1 = Q::new(0b1111, 3, 1, true);
        assert_eq!(fp1 << 1, Q::new(0b1110, 3, 1, true));
        assert_eq!(fp1 << 2, Q::new(0b1100, 3, 1, true));
        assert_eq!(fp1 << 3, Q::new(0b1000, 3, 1, true));
        assert_eq!(fp1 >> 1, Q::new(0b0111, 3, 1, true));
    }

    // #[test]
    // #[ignore]
    // fn test_index_right_idx_0() {
    //     let fp1 = Q::new(0b10010011, 6, 2, true); // 36.75
    //     let size = (fp1.m + fp1.n) as usize;

    //     assert_eq!(fp1.index(size..0).is_err(), true);
    //     assert_eq!(fp1.index(size - 1..0), Ok(Q::new(0b10010011, 6, 2, true)));
    //     assert_eq!(fp1.index(size - 2..0), Ok(Q::new(0b0010011, 5, 2, true)));
    //     assert_eq!(fp1.index(size - 3..0), Ok(Q::new(0b010011, 4, 2, true)));
    //     assert_eq!(fp1.index(size - 4..0), Ok(Q::new(0b10011, 3, 2, true)));
    //     assert_eq!(fp1.index(size - 5..0), Ok(Q::new(0b0011, 2, 2, true)));
    //     assert_eq!(fp1.index(size - 6..0), Ok(Q::new(0b011, 1, 2, true)));
    //     assert_eq!(fp1.index(size - 7..0), Ok(Q::new(0b11, 0, 2, true)));

    //     // assert_eq!(
    //     //     fp1.index(size - 8..0),
    //     //     Ok(Q::new(0b1, 0, 1, true))
    //     // );

    //     // assert_eq!(fp1.index(size - 9..0).is_err(), true);
    // }

    // #[test]
    // #[ignore]
    // fn test_index_left_idx_max() {
    //     let fp1 = Q::new(0b10010011, 6, 2, true); // 36.75
    //     let size = (fp1.m + fp1.n) as usize;

    //     assert_eq!(fp1.index(size..0).is_err(), true);

    //     assert_eq!(fp1.index(size - 1..0), Ok(Q::new(0b10010011, 6, 2, true)));

    //     assert_eq!(fp1.index(size - 1..1), Ok(Q::new(0b1001001, 6, 1, true)));

    //     assert_eq!(fp1.index(size - 1..2), Ok(Q::new(0b100100, 6, 0, true)));

    //     assert_eq!(fp1.index(size - 1..3), Ok(Q::new(0b10010, 5, 0, true)));

    //     assert_eq!(fp1.index(size - 1..4), Ok(Q::new(0b1001, 4, 0, true)));

    //     assert_eq!(fp1.index(size - 1..5), Ok(Q::new(0b100, 3, 0, true)));

    //     assert_eq!(fp1.index(size - 1..6), Ok(Q::new(0b10, 2, 0, true)));

    //     // assert_eq!(
    //     //     fp1.index(size-1..7),
    //     //     Ok(Q::new(0b1, 1, 0, true))
    //     // );

    //     assert_eq!(fp1.index(size - 8..8).is_err(), true);
    // }
}