qfall_math/integer/z/arithmetic/
sub.rs1use super::super::Z;
12use crate::{
13 integer_mod_q::Zq,
14 macros::arithmetics::{
15 arithmetic_assign_between_types, arithmetic_assign_trait_borrowed_to_owned,
16 arithmetic_between_types, arithmetic_trait_borrowed_to_owned,
17 arithmetic_trait_mixed_borrowed_owned,
18 },
19 rational::Q,
20};
21use flint_sys::{
22 fmpq::{fmpq, fmpq_set_fmpz_frac, fmpq_sub},
23 fmpz::{fmpz, fmpz_sub, fmpz_sub_si, fmpz_sub_ui},
24 fmpz_mod::fmpz_mod_sub_fmpz,
25};
26use std::ops::{Sub, SubAssign};
27
28impl SubAssign<&Z> for Z {
29 fn sub_assign(&mut self, other: &Self) {
51 unsafe { fmpz_sub(&mut self.value, &self.value, &other.value) };
52 }
53}
54impl SubAssign<i64> for Z {
55 fn sub_assign(&mut self, other: i64) {
57 unsafe { fmpz_sub_si(&mut self.value, &self.value, other) };
58 }
59}
60impl SubAssign<u64> for Z {
61 fn sub_assign(&mut self, other: u64) {
63 unsafe { fmpz_sub_ui(&mut self.value, &self.value, other) };
64 }
65}
66
67arithmetic_assign_trait_borrowed_to_owned!(SubAssign, sub_assign, Z, Z);
68arithmetic_assign_between_types!(SubAssign, sub_assign, Z, i64, i32 i16 i8);
69arithmetic_assign_between_types!(SubAssign, sub_assign, Z, u64, u32 u16 u8);
70
71impl Sub for &Z {
72 type Output = Z;
73 fn sub(self, other: Self) -> Self::Output {
94 let mut out = Z::default();
95 unsafe {
96 fmpz_sub(&mut out.value, &self.value, &other.value);
97 }
98 out
99 }
100}
101
102arithmetic_trait_borrowed_to_owned!(Sub, sub, Z, Z, Z);
103arithmetic_trait_mixed_borrowed_owned!(Sub, sub, Z, Z, Z);
104arithmetic_between_types!(Sub, sub, Z, Z, i64 i32 i16 i8 u64 u32 u16 u8);
105
106impl Sub<&Q> for &Z {
107 type Output = Q;
108
109 fn sub(self, other: &Q) -> Self::Output {
132 let mut out = Q::default();
133 let mut fmpq_1 = fmpq::default();
134 unsafe { fmpq_set_fmpz_frac(&mut fmpq_1, &self.value, &fmpz(1)) }
135 unsafe {
136 fmpq_sub(&mut out.value, &fmpq_1, &other.value);
137 }
138 out
139 }
140}
141
142arithmetic_trait_borrowed_to_owned!(Sub, sub, Z, Q, Q);
143arithmetic_trait_mixed_borrowed_owned!(Sub, sub, Z, Q, Q);
144arithmetic_between_types!(Sub, sub, Z, Q, f64 f32);
145
146impl Sub<&Zq> for &Z {
147 type Output = Zq;
148 fn sub(self, other: &Zq) -> Self::Output {
171 let mut out = fmpz(0);
172 unsafe {
173 fmpz_mod_sub_fmpz(
174 &mut out,
175 &self.value,
176 &other.value.value,
177 other.modulus.get_fmpz_mod_ctx_struct(),
178 );
179 }
180 Zq {
181 modulus: other.modulus.clone(),
182 value: Z { value: out },
183 }
184 }
185}
186
187arithmetic_trait_borrowed_to_owned!(Sub, sub, Z, Zq, Zq);
188arithmetic_trait_mixed_borrowed_owned!(Sub, sub, Z, Zq, Zq);
189
190#[cfg(test)]
191mod test_sub_assign {
192 use crate::integer::Z;
193
194 #[test]
196 fn correct_small() {
197 let mut a: Z = Z::MINUS_ONE;
198 let b = Z::ONE;
199 let c = Z::MINUS_ONE;
200
201 a -= &b;
202 assert_eq!(-2, a);
203 a -= &c;
204 assert_eq!(-1, a);
205 a -= &c;
206 assert_eq!(0, a);
207 a -= &c;
208 assert_eq!(1, a);
209 a -= &c;
210 assert_eq!(2, a);
211 a -= 2 * b;
212 assert_eq!(0, a);
213 }
214
215 #[test]
217 fn correct_large() {
218 let mut a: Z = Z::from(i64::MAX);
219 let b = Z::from(i64::MAX as u64 + 1);
220 let c = -1 * Z::from(u64::MAX);
221
222 a -= b;
223 assert_eq!(-1, a);
224 a -= c;
225 assert_eq!(u64::MAX - 1, a);
226 }
227
228 #[test]
230 fn availability() {
231 let mut a: Z = Z::from(42);
232 let b: Z = Z::from(1);
233
234 a -= &b;
235 a -= b;
236 a -= 1_u8;
237 a -= 1_u16;
238 a -= 1_u32;
239 a -= 1_u64;
240 a -= 1_i8;
241 a -= 1_i16;
242 a -= 1_i32;
243 a -= 1_i64;
244 }
245}
246
247#[cfg(test)]
248mod test_sub_between_types {
249 use crate::integer::Z;
250
251 #[test]
253 #[allow(clippy::op_ref)]
254 fn sub() {
255 let a: Z = Z::from(42);
256 let b: u64 = 1;
257 let c: u32 = 1;
258 let d: u16 = 1;
259 let e: u8 = 1;
260 let f: i64 = 1;
261 let g: i32 = 1;
262 let h: i16 = 1;
263 let i: i8 = 1;
264
265 let _: Z = &a - &b;
266 let _: Z = &a - &c;
267 let _: Z = &a - &d;
268 let _: Z = &a - &e;
269 let _: Z = &a - &f;
270 let _: Z = &a - &g;
271 let _: Z = &a - &h;
272 let _: Z = &a - &i;
273
274 let _: Z = &b - &a;
275 let _: Z = &c - &a;
276 let _: Z = &d - &a;
277 let _: Z = &e - &a;
278 let _: Z = &f - &a;
279 let _: Z = &g - &a;
280 let _: Z = &h - &a;
281 let _: Z = &i - &a;
282
283 let _: Z = &a - b;
284 let _: Z = &a - c;
285 let _: Z = &a - d;
286 let _: Z = &a - e;
287 let _: Z = &a - f;
288 let _: Z = &a - g;
289 let _: Z = &a - h;
290 let _: Z = &a - i;
291
292 let _: Z = &b - Z::from(42);
293 let _: Z = &c - Z::from(42);
294 let _: Z = &d - Z::from(42);
295 let _: Z = &e - Z::from(42);
296 let _: Z = &f - Z::from(42);
297 let _: Z = &g - Z::from(42);
298 let _: Z = &h - Z::from(42);
299 let _: Z = &i - Z::from(42);
300
301 let _: Z = Z::from(42) - &b;
302 let _: Z = Z::from(42) - &c;
303 let _: Z = Z::from(42) - &d;
304 let _: Z = Z::from(42) - &e;
305 let _: Z = Z::from(42) - &f;
306 let _: Z = Z::from(42) - &g;
307 let _: Z = Z::from(42) - &h;
308 let _: Z = Z::from(42) - &i;
309
310 let _: Z = b - &a;
311 let _: Z = c - &a;
312 let _: Z = d - &a;
313 let _: Z = e - &a;
314 let _: Z = f - &a;
315 let _: Z = g - &a;
316 let _: Z = h - &a;
317 let _: Z = i - &a;
318
319 let _: Z = Z::from(42) - b;
320 let _: Z = Z::from(42) - c;
321 let _: Z = Z::from(42) - d;
322 let _: Z = Z::from(42) - e;
323 let _: Z = Z::from(42) - f;
324 let _: Z = Z::from(42) - g;
325 let _: Z = Z::from(42) - h;
326 let _: Z = Z::from(42) - i;
327
328 let _: Z = b - Z::from(42);
329 let _: Z = c - Z::from(42);
330 let _: Z = d - Z::from(42);
331 let _: Z = e - Z::from(42);
332 let _: Z = f - Z::from(42);
333 let _: Z = g - Z::from(42);
334 let _: Z = h - Z::from(42);
335 let _: Z = i - Z::from(42);
336 }
337}
338
339#[cfg(test)]
340mod test_sub {
341 use super::Z;
342
343 #[test]
345 fn sub() {
346 let a: Z = Z::from(42);
347 let b: Z = Z::from(24);
348 let c: Z = a - b;
349 assert_eq!(c, Z::from(18));
350 }
351
352 #[test]
354 fn sub_borrow() {
355 let a: Z = Z::from(42);
356 let b: Z = Z::from(24);
357 let c: Z = &a - &b;
358 assert_eq!(c, Z::from(18));
359 }
360
361 #[test]
363 fn sub_first_borrowed() {
364 let a: Z = Z::from(42);
365 let b: Z = Z::from(24);
366 let c: Z = &a - b;
367 assert_eq!(c, Z::from(18));
368 }
369
370 #[test]
372 fn sub_second_borrowed() {
373 let a: Z = Z::from(42);
374 let b: Z = Z::from(24);
375 let c: Z = a - &b;
376 assert_eq!(c, Z::from(18));
377 }
378
379 #[test]
381 fn sub_large() {
382 let a: Z = Z::from(u64::MAX - 1);
383 let b: Z = Z::from(i64::MAX);
384 let c: Z = Z::from(738201034);
385
386 let d: Z = &a - &b;
387 let e: Z = &b - a;
388 let f: Z = b - c;
389
390 assert_eq!(d, Z::from(i64::MAX));
391 assert_eq!(e, Z::from(i64::MIN + 1));
392 assert_eq!(f, Z::from(i64::MAX - 738201034));
393 }
394}
395
396#[cfg(test)]
397mod test_sub_between_z_and_q {
398 use super::Z;
399 use crate::rational::Q;
400
401 #[test]
403 fn availability() {
404 let a: Z = Z::from(42);
405 let b: Q = Q::from((5, 7));
406
407 let _: Q = &a - &b;
408 let _: Q = &a - b.clone();
409 let _: Q = a.clone() - &b;
410 let _: Q = a.clone() - b;
411 let _: Q = &a - 0.5_f32;
412 let _: Q = &a - 0.5_f64;
413 let _: Q = a.clone() - 0.5_f32;
414 let _: Q = a.clone() - 0.5_f64;
415 let _: Q = 0.5_f32 - &a;
416 let _: Q = 0.5_f64 - &a;
417 let _: Q = 0.5_f32 - a.clone();
418 let _: Q = 0.5_f64 - a.clone();
419 }
420
421 #[test]
423 fn order_retained() {
424 let a = Z::from(4);
425
426 assert_eq!(2, &a - 2);
427 assert_eq!(Q::from((-2, 1)), 2 - &a);
428 }
429
430 #[test]
432 fn sub() {
433 let a: Z = Z::from(4);
434 let b: Q = Q::from((5, 7));
435 let c: Q = a - b;
436 assert_eq!(c, Q::from((23, 7)));
437 }
438
439 #[test]
441 fn sub_borrow() {
442 let a: Z = Z::from(4);
443 let b: Q = Q::from((5, 7));
444 let c: Q = &a - &b;
445 assert_eq!(c, Q::from((23, 7)));
446 }
447
448 #[test]
450 fn sub_first_borrowed() {
451 let a: Z = Z::from(4);
452 let b: Q = Q::from((5, 7));
453 let c: Q = &a - b;
454 assert_eq!(c, Q::from((23, 7)));
455 }
456
457 #[test]
459 fn sub_second_borrowed() {
460 let a: Z = Z::from(4);
461 let b: Q = Q::from((5, 7));
462 let c: Q = a - &b;
463 assert_eq!(c, Q::from((23, 7)));
464 }
465
466 #[test]
468 fn sub_large_numbers() {
469 let a: Z = Z::from(u64::MAX);
470 let b: Q = Q::from((1, u64::MAX));
471 let c: Q = Q::from((u64::MAX, 2));
472
473 let d: Q = &a - b;
474 let e: Q = a - c;
475
476 assert_eq!(d, Q::from(u64::MAX) - Q::from((1, u64::MAX)));
477 assert_eq!(e, Q::from(u64::MAX) - Q::from((u64::MAX, 2)));
478 }
479}
480
481#[cfg(test)]
482mod test_sub_between_z_and_zq {
483 use super::Z;
484 use crate::integer_mod_q::Zq;
485
486 #[test]
488 fn sub() {
489 let a: Z = Z::from(9);
490 let b: Zq = Zq::from((10, 11));
491 let c: Zq = a - b;
492 assert_eq!(c, Zq::from((10, 11)));
493 }
494
495 #[test]
497 fn sub_borrow() {
498 let a: Z = Z::from(9);
499 let b: Zq = Zq::from((4, 11));
500 let c: Zq = &a - &b;
501 assert_eq!(c, Zq::from((5, 11)));
502 }
503
504 #[test]
506 fn sub_first_borrowed() {
507 let a: Z = Z::from(9);
508 let b: Zq = Zq::from((4, 11));
509 let c: Zq = &a - b;
510 assert_eq!(c, Zq::from((5, 11)));
511 }
512
513 #[test]
515 fn sub_second_borrowed() {
516 let a: Z = Z::from(9);
517 let b: Zq = Zq::from((4, 11));
518 let c: Zq = a - &b;
519 assert_eq!(c, Zq::from((5, 11)));
520 }
521
522 #[test]
524 fn sub_large_numbers() {
525 let a: Z = Z::from(u64::MAX);
526 let b: Zq = Zq::from((i64::MAX, u64::MAX - 58));
527 let c: Zq = Zq::from((i64::MAX - 1, i64::MAX));
528
529 let d: Zq = &a - b;
530 let e: Zq = a - c;
531
532 assert_eq!(d, Zq::from(((u64::MAX - 1) / 2 + 1, u64::MAX - 58)));
533 assert_eq!(e, Zq::from((2, i64::MAX)));
534 }
535}