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