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
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// Copyright © 2023 Niklas Siemer
//
// This file is part of qFALL-math.
//
// qFALL-math is free software: you can redistribute it and/or modify it under
// the terms of the Mozilla Public License Version 2.0 as published by the
// Mozilla Foundation. See <https://mozilla.org/en-US/MPL/2.0/>.
//! This module contains implementations for comparison of [`MatZ`].
use super::MatZ;
use crate::{integer::Z, macros::compare_base::compare_base_default, traits::CompareBase};
use flint_sys::fmpz_mat::fmpz_mat_equal;
impl PartialEq for MatZ {
/// Checks if two [`MatZ`] instances are equal. Used by the `==` and `!=` operators.
///
/// Parameters:
/// - `other`: the other value that is compare against `self`
///
/// Returns `true` if the elements are equal, otherwise `false`.
///
/// # Examples
/// ```
/// use qfall_math::integer::MatZ;
/// use std::str::FromStr;
///
/// let a = MatZ::from_str("[[1, 2],[3, 4]]").unwrap();
/// let b = MatZ::from_str("[[1, 2],[2, 4]]").unwrap();
///
/// // These are all equivalent and return false.
/// let compared: bool = (a == b);
/// # assert!(!compared);
/// let compared: bool = (&a == &b);
/// # assert!(!compared);
/// let compared: bool = (a.eq(&b));
/// # assert!(!compared);
/// let compared: bool = (MatZ::eq(&a, &b));
/// # assert!(!compared);
/// ```
fn eq(&self, other: &Self) -> bool {
unsafe { fmpz_mat_equal(&self.matrix, &other.matrix) != 0 }
}
}
compare_base_default!(MatZ for MatZ);
impl<Integer: Into<Z>> CompareBase<Integer> for MatZ {}
// With the [`Eq`] trait, `a == a` is always true.
// This is not guaranteed by the [`PartialEq`] trait.
impl Eq for MatZ {}
/// Test that the [`PartialEq`] trait is correctly implemented.
#[cfg(test)]
mod test_partial_eq {
use super::MatZ;
use crate::traits::MatrixSetEntry;
use std::str::FromStr;
/// Ensures that different instantiations do not break the equality between matrices
#[test]
fn equality_between_instantiations() {
let a = MatZ::from_str("[[0, 1],[0, 0]]").unwrap();
let mut b = MatZ::new(2, 2);
b.set_entry(0, 1, 1).unwrap();
assert_eq!(a, b);
}
/// Checks that large and small entries (and different points in storage) do not break equality
#[test]
fn equality_for_large_and_small_entries() {
let a = MatZ::from_str(&format!(
"[[{}, {}, 1],[-10, 10, 0],[0, 1, -10]]",
i64::MIN,
i64::MAX
))
.unwrap();
let b = MatZ::from_str(&format!(
"[[{}, {}, 1],[-10, 10, 0],[0, 1, -10]]",
i64::MIN,
i64::MAX
))
.unwrap();
assert_eq!(&a, &b);
}
/// Checks that different unequal matrices are unequal
#[test]
fn not_equal() {
let a = MatZ::from_str(&format!("[[{}, {}],[-10, 10]]", i64::MIN, i64::MAX)).unwrap();
let b = MatZ::from_str(&format!("[[0, {}],[-10, 10]]", i64::MAX)).unwrap();
let c =
MatZ::from_str(&format!("[[{}, {}],[-10, 10],[0, 0]]", i64::MIN, i64::MAX)).unwrap();
let d = MatZ::from_str(&format!("[[{}, {}]]", i64::MIN, i64::MAX)).unwrap();
let e = MatZ::from_str("[[0]]").unwrap();
assert_ne!(&a, &b);
assert_ne!(&a, &c);
assert_ne!(&a, &d);
assert_ne!(&a, &e);
assert_ne!(&b, &c);
assert_ne!(&b, &d);
assert_ne!(&b, &e);
assert_ne!(&c, &d);
assert_ne!(&c, &e);
assert_ne!(&d, &e);
}
}
/// Test that the [`CompareBase`] trait uses the default implementation.
#[cfg(test)]
mod test_compare_base {
use crate::{
integer::{MatZ, Z},
traits::CompareBase,
};
use std::str::FromStr;
/// Ensures that the [`CompareBase`] trait uses the default implementation
/// and is available for all types it would be checked against.
#[test]
fn availability() {
let one_1 = MatZ::from_str("[[2,5,-7],[2,3,4]]").unwrap();
assert!(one_1.compare_base(&MatZ::new(1, 1)));
assert!(one_1.compare_base(&Z::ONE));
assert!(one_1.compare_base(&0_i8));
assert!(one_1.compare_base(&0_i16));
assert!(one_1.compare_base(&0_i32));
assert!(one_1.compare_base(&0_i64));
assert!(one_1.compare_base(&0_u8));
assert!(one_1.compare_base(&0_u16));
assert!(one_1.compare_base(&0_u32));
assert!(one_1.compare_base(&0_u64));
assert!(one_1.call_compare_base_error(&MatZ::new(1, 1)).is_none());
assert!(one_1.call_compare_base_error(&Z::ONE).is_none());
assert!(one_1.call_compare_base_error(&0_i8).is_none());
assert!(one_1.call_compare_base_error(&0_i16).is_none());
assert!(one_1.call_compare_base_error(&0_i32).is_none());
assert!(one_1.call_compare_base_error(&0_i64).is_none());
assert!(one_1.call_compare_base_error(&0_u8).is_none());
assert!(one_1.call_compare_base_error(&0_u16).is_none());
assert!(one_1.call_compare_base_error(&0_u32).is_none());
assert!(one_1.call_compare_base_error(&0_u64).is_none());
}
}