qfall_math/integer/z/arithmetic/
modulo.rs1use flint_sys::{fmpz::fmpz_mod, fmpz_mod::fmpz_mod_set_fmpz};
12
13use super::super::Z;
14use crate::{
15 integer_mod_q::Modulus,
16 macros::arithmetics::{
17 arithmetic_between_types, arithmetic_trait_borrowed_to_owned,
18 arithmetic_trait_mixed_borrowed_owned,
19 },
20};
21use std::ops::Rem;
22
23impl Rem for &Z {
24 type Output = Z;
25 fn rem(self, modulus: Self) -> Self::Output {
47 assert!(modulus > &1, "Modulus can not be smaller than 2.");
48 let mut out = Z::default();
49 unsafe { fmpz_mod(&mut out.value, &self.value, &modulus.value) };
50 out
51 }
52}
53
54impl Rem<&Modulus> for &Z {
55 type Output = Z;
56 fn rem(self, modulus: &Modulus) -> Self::Output {
76 let mut out = Z::default();
77 unsafe {
78 fmpz_mod_set_fmpz(
79 &mut out.value,
80 &self.value,
81 modulus.get_fmpz_mod_ctx_struct(),
82 )
83 };
84 out
85 }
86}
87
88arithmetic_trait_borrowed_to_owned!(Rem, rem, Z, Z, Z);
89arithmetic_trait_mixed_borrowed_owned!(Rem, rem, Z, Z, Z);
90arithmetic_trait_borrowed_to_owned!(Rem, rem, Z, Modulus, Z);
91arithmetic_trait_mixed_borrowed_owned!(Rem, rem, Z, Modulus, Z);
92arithmetic_between_types!(Rem, rem, Z, Z, i64 i32 i16 i8 u64 u32 u16 u8);
93
94#[cfg(test)]
95mod test_rem {
96 use super::Z;
97 use crate::integer_mod_q::Modulus;
98
99 #[test]
101 fn rem() {
102 let a: Z = Z::from(42);
103 let b: Z = Z::from(24);
104 let c1: Z = a.clone() % b;
105 let c2: Z = a % Modulus::from(24);
106 assert_eq!(c1, 18);
107 assert_eq!(c2, 18);
108 }
109
110 #[test]
112 fn rem_borrow() {
113 let a: Z = Z::from(42);
114 let b: Z = Z::from(24);
115 let c1: Z = &a % &b;
116 let c2: Z = &a % &Modulus::from(24);
117 assert_eq!(c1, 18);
118 assert_eq!(c2, 18);
119 }
120
121 #[test]
123 fn rem_first_borrowed() {
124 let a: Z = Z::from(42);
125 let b: Z = Z::from(24);
126 let c1: Z = &a % b;
127 let c2: Z = &a % Modulus::from(24);
128 assert_eq!(c1, 18);
129 assert_eq!(c2, 18);
130 }
131
132 #[test]
134 fn rem_second_borrowed() {
135 let a: Z = Z::from(42);
136 let b: Z = Z::from(24);
137 let c1: Z = a.clone() % &b;
138 let c2: Z = a % &Modulus::from(24);
139 assert_eq!(c1, 18);
140 assert_eq!(c2, 18);
141 }
142
143 #[test]
145 fn rem_negative_representation() {
146 let a: Z = Z::from(-2);
147 let b: Z = Z::from(24);
148 let c1: Z = a.clone() % &b;
149 let c2: Z = &a % &Modulus::from(24);
150 assert_eq!(c1, 22);
151 assert_eq!(c2, 22);
152 }
153
154 #[test]
156 fn rem_large_numbers() {
157 let a: Z = Z::from(u64::MAX);
158 let b: Z = Z::from(u64::MAX - 2);
159
160 let c1: Z = a.clone() % &b;
161 let c2: Z = a % &Modulus::from(u64::MAX - 2);
162 assert_eq!(c1, 2);
163 assert_eq!(c2, 2);
164 }
165
166 #[test]
168 #[should_panic]
169 fn rem_negative_error() {
170 let a: Z = Z::from(42);
171 let b: Z = Z::from(-24);
172 _ = &a % &b;
173 }
174
175 #[test]
177 #[should_panic]
178 fn zero_modulus() {
179 _ = Z::from(15) % 0;
180 }
181
182 #[test]
184 fn availability() {
185 let _ = Z::ONE % 2u8;
186 let _ = Z::ONE % 2u16;
187 let _ = Z::ONE % 2u32;
188 let _ = Z::ONE % 2u64;
189 let _ = Z::ONE % 2i8;
190 let _ = Z::ONE % 2i16;
191 let _ = Z::ONE % 2i32;
192 let _ = Z::ONE % 2i64;
193 let _ = Z::ONE % Z::from(2);
194 let _ = Z::ONE % Modulus::from(2);
195
196 let _ = &Z::ONE % 2u8;
197 let _ = 1u8 % Z::from(2);
198 let _ = 1u8 % &Z::from(2);
199 }
200}