qfall_math/integer/mat_z/
cmp.rs

1// Copyright © 2023 Niklas Siemer
2//
3// This file is part of qFALL-math.
4//
5// qFALL-math is free software: you can redistribute it and/or modify it under
6// the terms of the Mozilla Public License Version 2.0 as published by the
7// Mozilla Foundation. See <https://mozilla.org/en-US/MPL/2.0/>.
8
9//! This module contains implementations for comparison of [`MatZ`].
10
11use super::MatZ;
12use crate::{integer::Z, macros::compare_base::compare_base_default, traits::CompareBase};
13use flint_sys::fmpz_mat::fmpz_mat_equal;
14
15impl PartialEq for MatZ {
16    /// Checks if two [`MatZ`] instances are equal. Used by the `==` and `!=` operators.
17    ///
18    /// Parameters:
19    /// - `other`: the other value that is compare against `self`
20    ///
21    /// Returns `true` if the elements are equal, otherwise `false`.
22    ///
23    /// # Examples
24    /// ```
25    /// use qfall_math::integer::MatZ;
26    /// use std::str::FromStr;
27    ///
28    /// let a = MatZ::from_str("[[1, 2],[3, 4]]").unwrap();
29    /// let b = MatZ::from_str("[[1, 2],[2, 4]]").unwrap();
30    ///
31    /// // These are all equivalent and return false.
32    /// let compared: bool = (a == b);
33    /// # assert!(!compared);
34    /// let compared: bool = (&a == &b);
35    /// # assert!(!compared);
36    /// let compared: bool = (a.eq(&b));
37    /// # assert!(!compared);
38    /// let compared: bool = (MatZ::eq(&a, &b));
39    /// # assert!(!compared);
40    /// ```
41    fn eq(&self, other: &Self) -> bool {
42        unsafe { fmpz_mat_equal(&self.matrix, &other.matrix) != 0 }
43    }
44}
45
46compare_base_default!(MatZ for MatZ);
47impl<Integer: Into<Z>> CompareBase<Integer> for MatZ {}
48
49// With the [`Eq`] trait, `a == a` is always true.
50// This is not guaranteed by the [`PartialEq`] trait.
51impl Eq for MatZ {}
52
53/// Test that the [`PartialEq`] trait is correctly implemented.
54#[cfg(test)]
55mod test_partial_eq {
56    use super::MatZ;
57    use crate::traits::MatrixSetEntry;
58    use std::str::FromStr;
59
60    /// Ensures that different instantiations do not break the equality between matrices
61    #[test]
62    fn equality_between_instantiations() {
63        let a = MatZ::from_str("[[0, 1],[0, 0]]").unwrap();
64        let mut b = MatZ::new(2, 2);
65        b.set_entry(0, 1, 1).unwrap();
66
67        assert_eq!(a, b);
68    }
69
70    /// Checks that large and small entries (and different points in storage) do not break equality
71    #[test]
72    fn equality_for_large_and_small_entries() {
73        let a = MatZ::from_str(&format!(
74            "[[{}, {}, 1],[-10, 10, 0],[0, 1, -10]]",
75            i64::MIN,
76            i64::MAX
77        ))
78        .unwrap();
79        let b = MatZ::from_str(&format!(
80            "[[{}, {}, 1],[-10, 10, 0],[0, 1, -10]]",
81            i64::MIN,
82            i64::MAX
83        ))
84        .unwrap();
85
86        assert_eq!(&a, &b);
87    }
88
89    /// Checks that different unequal matrices are unequal
90    #[test]
91    fn not_equal() {
92        let a = MatZ::from_str(&format!("[[{}, {}],[-10, 10]]", i64::MIN, i64::MAX)).unwrap();
93        let b = MatZ::from_str(&format!("[[0, {}],[-10, 10]]", i64::MAX)).unwrap();
94        let c =
95            MatZ::from_str(&format!("[[{}, {}],[-10, 10],[0, 0]]", i64::MIN, i64::MAX)).unwrap();
96        let d = MatZ::from_str(&format!("[[{}, {}]]", i64::MIN, i64::MAX)).unwrap();
97        let e = MatZ::from_str("[[0]]").unwrap();
98
99        assert_ne!(&a, &b);
100        assert_ne!(&a, &c);
101        assert_ne!(&a, &d);
102        assert_ne!(&a, &e);
103        assert_ne!(&b, &c);
104        assert_ne!(&b, &d);
105        assert_ne!(&b, &e);
106        assert_ne!(&c, &d);
107        assert_ne!(&c, &e);
108        assert_ne!(&d, &e);
109    }
110}
111
112/// Test that the [`CompareBase`] trait uses the default implementation.
113#[cfg(test)]
114mod test_compare_base {
115    use crate::{
116        integer::{MatZ, Z},
117        traits::CompareBase,
118    };
119    use std::str::FromStr;
120
121    /// Ensures that the [`CompareBase`] trait uses the default implementation
122    /// and is available for all types it would be checked against.
123    #[test]
124    fn availability() {
125        let one_1 = MatZ::from_str("[[2,5,-7],[2,3,4]]").unwrap();
126
127        assert!(one_1.compare_base(&MatZ::new(1, 1)));
128        assert!(one_1.compare_base(&Z::ONE));
129        assert!(one_1.compare_base(&0_i8));
130        assert!(one_1.compare_base(&0_i16));
131        assert!(one_1.compare_base(&0_i32));
132        assert!(one_1.compare_base(&0_i64));
133        assert!(one_1.compare_base(&0_u8));
134        assert!(one_1.compare_base(&0_u16));
135        assert!(one_1.compare_base(&0_u32));
136        assert!(one_1.compare_base(&0_u64));
137
138        assert!(one_1.call_compare_base_error(&MatZ::new(1, 1)).is_none());
139        assert!(one_1.call_compare_base_error(&Z::ONE).is_none());
140        assert!(one_1.call_compare_base_error(&0_i8).is_none());
141        assert!(one_1.call_compare_base_error(&0_i16).is_none());
142        assert!(one_1.call_compare_base_error(&0_i32).is_none());
143        assert!(one_1.call_compare_base_error(&0_i64).is_none());
144        assert!(one_1.call_compare_base_error(&0_u8).is_none());
145        assert!(one_1.call_compare_base_error(&0_u16).is_none());
146        assert!(one_1.call_compare_base_error(&0_u32).is_none());
147        assert!(one_1.call_compare_base_error(&0_u64).is_none());
148    }
149}