rust_tensors/
matrix_address.rs

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
use std::cmp::Ordering;
use std::fmt::{Display, Formatter};
use crate::addressable::Addressable;

#[derive(Eq, PartialEq, Ord, Copy, Clone, Debug)]
pub struct MatrixAddress {
    pub x: i64,
    pub y: i64,
}

impl PartialOrd<Self> for MatrixAddress {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        match self.y.cmp(&other.y) {
            Ordering::Less => Some(Ordering::Less),
            Ordering::Equal => match self.x.cmp(&other.x) {
                Ordering::Less => Some(Ordering::Less),
                Ordering::Equal => Some(Ordering::Equal),
                Ordering::Greater => Some(Ordering::Greater),
            },
            Ordering::Greater => Some(Ordering::Greater),
        }
    }
}

impl Addressable for MatrixAddress {
    fn get_dimension_count() -> u32 {
        2
    }

    fn new_from_value_vec(values: Vec<i64>) -> MatrixAddress {
        MatrixAddress {
            x: values[0],
            y: values[1],
        }
    }

    fn get_item_at_dimension_index(&self, dimension_index: u32) -> &i64 {
        match dimension_index {
            0 => &self.x,
            1 => &self.y,
            _ => panic!("Unexpected Dimension Index Accessed"),
        }
    }
}

impl Display for MatrixAddress {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "({}, {})", self.x, self.y)
    }
}

#[allow(unused)]
impl MatrixAddress {
    fn new(x: i64, y: i64) -> MatrixAddress {
        MatrixAddress { x, y }
    }
}

#[cfg(test)]
mod tests {
    use proptest::{prop_assert_eq, proptest};
    use crate::addressable::Addressable;
    use crate::matrix_address::MatrixAddress;

    proptest! {
        #[test]
        fn doesnt_crash(x1 in -1_000_000_000i64..1_000_000_000i64, y1 in -1_000_000_000i64..1_000_000_000i64, x2 in -1_000_000_000i64..1_000_000_000i64, y2 in -1_000_000_000i64..1_000_000_000i64) {
            let a1 = MatrixAddress{x: x1, y: y1};
            let a2 = MatrixAddress{x: x2,y: y2};
            a1.add(&a2);
            a2.add(&a1);
            a1.subtract(&a2);
            a2.subtract(&a1);
            a1.difference(&a2);
            a2.difference(&a1);
            a1.distance(&a2);
            a2.distance(&a1);
            a1.scale(x2 as f64);
        }

        #[test]
        fn operation_consistency(x1 in -1_000_000_000i64..1_000_000_000i64, y1 in -1_000_000_000i64..1_000_000_000i64, x2 in -1_000_000_000i64..1_000_000_000i64, y2 in -1_000_000_000i64..1_000_000_000i64) {
            let a1 = MatrixAddress{x: x1, y: y1};
            let a2 = MatrixAddress{x: x2,y: y2};
            prop_assert_eq!(a1.add(&a2).subtract(&a2), a1);
            prop_assert_eq!(a1.subtract(&a2).add(&a2), a1);
        }

        #[test]
        fn operation_accuracy(x1 in -1_000_000i64..1_000_000i64, y1 in -1_000_000i64..1_000_000i64, x2 in -1_000_000i64..1_000_000i64, y2 in -1_000_000i64..1_000_000i64) {
            let a1 = MatrixAddress{x: x1, y: y1};
            let a2 = MatrixAddress{x: x2,y: y2};
            prop_assert_eq!(a1.add(&a2), MatrixAddress{x: x1 + x2,y: y1 + y2});
            prop_assert_eq!(a1.subtract(&a2), MatrixAddress{x: x1 - x2,y: y1 - y2});
            prop_assert_eq!(a1.scale(x2 as f64), MatrixAddress{x: x1 * x2,y: y1 * x2});
            prop_assert_eq!(a1.distance(&a2), (((x1 - x2).pow(2) as f64) + ((y1 - y2).pow(2) as f64)).sqrt());
        }
    }
}