1use crate::ext::xmpz;
18use crate::ext::xmpz::OptInteger;
19use crate::integer::MiniInteger;
20use crate::ops::{
21 AddFrom, BitAndFrom, BitOrFrom, BitXorFrom, DivFrom, MulFrom, NegAssign, NotAssign, Pow,
22 PowAssign, RemFrom, SubFrom,
23};
24use crate::{Assign, Complete, Integer};
25use az::{CheckedAs, CheckedCast};
26use core::ffi::{c_long, c_ulong};
27use core::iter::{Product, Sum};
28use core::ops::{
29 Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
30 Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign,
31};
32
33arith_unary! {
34 Integer;
35 xmpz::neg;
36 Neg { neg }
37 NegAssign { neg_assign }
38 NegIncomplete
39}
40arith_binary_self! {
41 Integer;
42 xmpz::add;
43 Add { add }
44 AddAssign { add_assign }
45 AddFrom { add_from }
46 AddIncomplete;
47 rhs_has_more_alloc
48}
49arith_binary_self! {
50 Integer;
51 xmpz::sub;
52 Sub { sub }
53 SubAssign { sub_assign }
54 SubFrom { sub_from }
55 SubIncomplete;
56 rhs_has_more_alloc
57}
58arith_binary_self! {
59 Integer;
60 xmpz::mul;
61 Mul { mul }
62 MulAssign { mul_assign }
63 MulFrom { mul_from }
64 MulIncomplete;
65 rhs_has_more_alloc
66}
67arith_binary_self! {
68 Integer;
69 xmpz::tdiv_q;
70 Div { div }
71 DivAssign { div_assign }
72 DivFrom { div_from }
73 DivIncomplete;
74 rhs_has_more_alloc
75}
76arith_binary_self! {
77 Integer;
78 xmpz::tdiv_r;
79 Rem { rem }
80 RemAssign { rem_assign }
81 RemFrom { rem_from }
82 RemIncomplete;
83 rhs_has_more_alloc
84}
85arith_unary! {
86 Integer;
87 xmpz::com;
88 Not { not }
89 NotAssign { not_assign }
90 NotIncomplete
91}
92arith_binary_self! {
93 Integer;
94 xmpz::and;
95 BitAnd { bitand }
96 BitAndAssign { bitand_assign }
97 BitAndFrom { bitand_from }
98 BitAndIncomplete;
99 rhs_has_more_alloc
100}
101arith_binary_self! {
102 Integer;
103 xmpz::ior;
104 BitOr { bitor }
105 BitOrAssign { bitor_assign }
106 BitOrFrom { bitor_from }
107 BitOrIncomplete;
108 rhs_has_more_alloc
109}
110arith_binary_self! {
111 Integer;
112 xmpz::xor;
113 BitXor { bitxor }
114 BitXorAssign { bitxor_assign }
115 BitXorFrom { bitxor_from }
116 BitXorIncomplete;
117 rhs_has_more_alloc
118}
119
120arith_prim_commut! {
121 Integer;
122 PrimOps::add;
123 Add { add }
124 AddAssign { add_assign }
125 AddFrom { add_from }
126 i8, AddI8Incomplete;
127 i16, AddI16Incomplete;
128 i32, AddI32Incomplete;
129 i64, AddI64Incomplete;
130 i128, AddI128Incomplete;
131 isize, AddIsizeIncomplete;
132 u8, AddU8Incomplete;
133 u16, AddU16Incomplete;
134 u32, AddU32Incomplete;
135 u64, AddU64Incomplete;
136 u128, AddU128Incomplete;
137 usize, AddUsizeIncomplete;
138}
139arith_prim_noncommut! {
140 Integer;
141 PrimOps::sub, PrimOps::sub_from;
142 Sub { sub }
143 SubAssign { sub_assign }
144 SubFrom { sub_from }
145 i8, SubI8Incomplete, SubFromI8Incomplete;
146 i16, SubI16Incomplete, SubFromI16Incomplete;
147 i32, SubI32Incomplete, SubFromI32Incomplete;
148 i64, SubI64Incomplete, SubFromI64Incomplete;
149 i128, SubI128Incomplete, SubFromI128Incomplete;
150 isize, SubIsizeIncomplete, SubFromIsizeIncomplete;
151 u8, SubU8Incomplete, SubFromU8Incomplete;
152 u16, SubU16Incomplete, SubFromU16Incomplete;
153 u32, SubU32Incomplete, SubFromU32Incomplete;
154 u64, SubU64Incomplete, SubFromU64Incomplete;
155 u128, SubU128Incomplete, SubFromU128Incomplete;
156 usize, SubUsizeIncomplete, SubFromUsizeIncomplete;
157}
158arith_prim_commut! {
159 Integer;
160 PrimOps::mul;
161 Mul { mul }
162 MulAssign { mul_assign }
163 MulFrom { mul_from }
164 i8, MulI8Incomplete;
165 i16, MulI16Incomplete;
166 i32, MulI32Incomplete;
167 i64, MulI64Incomplete;
168 i128, MulI128Incomplete;
169 isize, MulIsizeIncomplete;
170 u8, MulU8Incomplete;
171 u16, MulU16Incomplete;
172 u32, MulU32Incomplete;
173 u64, MulU64Incomplete;
174 u128, MulU128Incomplete;
175 usize, MulUsizeIncomplete;
176}
177arith_prim_noncommut! {
178 Integer;
179 PrimOps::div, PrimOps::div_from;
180 Div { div }
181 DivAssign { div_assign }
182 DivFrom { div_from }
183 i8, DivI8Incomplete, DivFromI8Incomplete;
184 i16, DivI16Incomplete, DivFromI16Incomplete;
185 i32, DivI32Incomplete, DivFromI32Incomplete;
186 i64, DivI64Incomplete, DivFromI64Incomplete;
187 i128, DivI128Incomplete, DivFromI128Incomplete;
188 isize, DivIsizeIncomplete, DivFromIsizeIncomplete;
189 u8, DivU8Incomplete, DivFromU8Incomplete;
190 u16, DivU16Incomplete, DivFromU16Incomplete;
191 u32, DivU32Incomplete, DivFromU32Incomplete;
192 u64, DivU64Incomplete, DivFromU64Incomplete;
193 u128, DivU128Incomplete, DivFromU128Incomplete;
194 usize, DivUsizeIncomplete, DivFromUsizeIncomplete;
195}
196arith_prim_noncommut! {
197 Integer;
198 PrimOps::rem, PrimOps::rem_from;
199 Rem { rem }
200 RemAssign { rem_assign }
201 RemFrom { rem_from }
202 i8, RemI8Incomplete, RemFromI8Incomplete;
203 i16, RemI16Incomplete, RemFromI16Incomplete;
204 i32, RemI32Incomplete, RemFromI32Incomplete;
205 i64, RemI64Incomplete, RemFromI64Incomplete;
206 i128, RemI128Incomplete, RemFromI128Incomplete;
207 isize, RemIsizeIncomplete, RemFromIsizeIncomplete;
208 u8, RemU8Incomplete, RemFromU8Incomplete;
209 u16, RemU16Incomplete, RemFromU16Incomplete;
210 u32, RemU32Incomplete, RemFromU32Incomplete;
211 u64, RemU64Incomplete, RemFromU64Incomplete;
212 u128, RemU128Incomplete, RemFromU128Incomplete;
213 usize, RemUsizeIncomplete, RemFromUsizeIncomplete;
214}
215arith_prim_commut! {
216 Integer;
217 PrimOps::and;
218 BitAnd { bitand }
219 BitAndAssign { bitand_assign }
220 BitAndFrom { bitand_from }
221 i8, BitAndI8Incomplete;
222 i16, BitAndI16Incomplete;
223 i32, BitAndI32Incomplete;
224 i64, BitAndI64Incomplete;
225 i128, BitAndI128Incomplete;
226 isize, BitAndIsizeIncomplete;
227 u8, BitAndU8Incomplete;
228 u16, BitAndU16Incomplete;
229 u32, BitAndU32Incomplete;
230 u64, BitAndU64Incomplete;
231 u128, BitAndU128Incomplete;
232 usize, BitAndUsizeIncomplete;
233}
234arith_prim_commut! {
235 Integer;
236 PrimOps::ior;
237 BitOr { bitor }
238 BitOrAssign { bitor_assign }
239 BitOrFrom { bitor_from }
240 i8, BitOrI8Incomplete;
241 i16, BitOrI16Incomplete;
242 i32, BitOrI32Incomplete;
243 i64, BitOrI64Incomplete;
244 i128, BitOrI128Incomplete;
245 isize, BitOrIsizeIncomplete;
246 u8, BitOrU8Incomplete;
247 u16, BitOrU16Incomplete;
248 u32, BitOrU32Incomplete;
249 u64, BitOrU64Incomplete;
250 u128, BitOrU128Incomplete;
251 usize, BitOrUsizeIncomplete;
252}
253arith_prim_commut! {
254 Integer;
255 PrimOps::xor;
256 BitXor { bitxor }
257 BitXorAssign { bitxor_assign }
258 BitXorFrom { bitxor_from }
259 i8, BitXorI8Incomplete;
260 i16, BitXorI16Incomplete;
261 i32, BitXorI32Incomplete;
262 i64, BitXorI64Incomplete;
263 i128, BitXorI128Incomplete;
264 isize, BitXorIsizeIncomplete;
265 u8, BitXorU8Incomplete;
266 u16, BitXorU16Incomplete;
267 u32, BitXorU32Incomplete;
268 u64, BitXorU64Incomplete;
269 u128, BitXorU128Incomplete;
270 usize, BitXorUsizeIncomplete;
271}
272
273arith_prim! {
274 Integer;
275 xmpz::shl_i32;
276 Shl { shl }
277 ShlAssign { shl_assign }
278 i32, ShlI32Incomplete;
279}
280arith_prim! {
281 Integer;
282 xmpz::shr_i32;
283 Shr { shr }
284 ShrAssign { shr_assign }
285 i32, ShrI32Incomplete;
286}
287arith_prim! {
288 Integer;
289 xmpz::shl_u32;
290 Shl { shl }
291 ShlAssign { shl_assign }
292 u32, ShlU32Incomplete;
293}
294arith_prim! {
295 Integer;
296 xmpz::shr_u32;
297 Shr { shr }
298 ShrAssign { shr_assign }
299 u32, ShrU32Incomplete;
300}
301arith_prim! {
302 Integer;
303 xmpz::shl_isize;
304 Shl { shl }
305 ShlAssign { shl_assign }
306 isize, ShlIsizeIncomplete;
307}
308arith_prim! {
309 Integer;
310 xmpz::shr_isize;
311 Shr { shr }
312 ShrAssign { shr_assign }
313 isize, ShrIsizeIncomplete;
314}
315arith_prim! {
316 Integer;
317 xmpz::shl_usize;
318 Shl { shl }
319 ShlAssign { shl_assign }
320 usize, ShlUsizeIncomplete;
321}
322arith_prim! {
323 Integer;
324 xmpz::shr_usize;
325 Shr { shr }
326 ShrAssign { shr_assign }
327 usize, ShrUsizeIncomplete;
328}
329arith_prim! {
330 Integer;
331 xmpz::pow_u32;
332 Pow { pow }
333 PowAssign { pow_assign }
334 u32, PowU32Incomplete;
335}
336
337mul_op_commut! {
338 Integer;
339 xmpz::addmul;
340 Add { add }
341 AddAssign { add_assign }
342 AddFrom { add_from }
343 MulIncomplete, AddMulIncomplete;
344}
345mul_op_noncommut! {
346 Integer;
347 xmpz::submul, xmpz::mulsub;
348 Sub { sub }
349 SubAssign { sub_assign }
350 SubFrom { sub_from }
351 MulIncomplete, SubMulIncomplete, SubMulFromIncomplete;
352}
353mul_op_commut! {
354 Integer;
355 PrimOps::addmul;
356 Add { add }
357 AddAssign { add_assign }
358 AddFrom { add_from }
359 MulI8Incomplete, AddMulI8Incomplete;
360 MulI16Incomplete, AddMulI16Incomplete;
361 MulI32Incomplete, AddMulI32Incomplete;
362 MulI64Incomplete, AddMulI64Incomplete;
363 MulI128Incomplete, AddMulI128Incomplete;
364 MulIsizeIncomplete, AddMulIsizeIncomplete;
365 MulU8Incomplete, AddMulU8Incomplete;
366 MulU16Incomplete, AddMulU16Incomplete;
367 MulU32Incomplete, AddMulU32Incomplete;
368 MulU64Incomplete, AddMulU64Incomplete;
369 MulU128Incomplete, AddMulU128Incomplete;
370 MulUsizeIncomplete, AddMulUsizeIncomplete;
371}
372mul_op_noncommut! {
373 Integer;
374 PrimOps::submul, PrimOps::mulsub;
375 Sub { sub }
376 SubAssign { sub_assign }
377 SubFrom { sub_from }
378 MulI8Incomplete, SubMulI8Incomplete, SubMulFromI8Incomplete;
379 MulI16Incomplete, SubMulI16Incomplete, SubMulFromI16Incomplete;
380 MulI32Incomplete, SubMulI32Incomplete, SubMulFromI32Incomplete;
381 MulI64Incomplete, SubMulI64Incomplete, SubMulFromI64Incomplete;
382 MulI128Incomplete, SubMulI128Incomplete, SubMulFromI128Incomplete;
383 MulIsizeIncomplete, SubMulIsizeIncomplete, SubMulFromIsizeIncomplete;
384 MulU8Incomplete, SubMulU8Incomplete, SubMulFromU8Incomplete;
385 MulU16Incomplete, SubMulU16Incomplete, SubMulFromU16Incomplete;
386 MulU32Incomplete, SubMulU32Incomplete, SubMulFromU32Incomplete;
387 MulU64Incomplete, SubMulU64Incomplete, SubMulFromU64Incomplete;
388 MulU128Incomplete, SubMulU128Incomplete, SubMulFromU128Incomplete;
389 MulUsizeIncomplete, SubMulUsizeIncomplete, SubMulFromUsizeIncomplete;
390}
391
392trait PrimOps<Long>: AsLong {
393 fn add<O: OptInteger>(rop: &mut Integer, op1: O, op2: Self);
394 fn sub<O: OptInteger>(rop: &mut Integer, op1: O, op2: Self);
395 fn sub_from<O: OptInteger>(rop: &mut Integer, op1: Self, op2: O);
396 fn mul<O: OptInteger>(rop: &mut Integer, op1: O, op2: Self);
397 fn div<O: OptInteger>(rop: &mut Integer, op1: O, op2: Self);
398 fn div_from<O: OptInteger>(rop: &mut Integer, op1: Self, op2: O);
399 fn rem<O: OptInteger>(rop: &mut Integer, op1: O, op2: Self);
400 fn rem_from<O: OptInteger>(rop: &mut Integer, op1: Self, op2: O);
401 fn and<O: OptInteger>(rop: &mut Integer, op1: O, op2: Self);
402 fn ior<O: OptInteger>(rop: &mut Integer, op1: O, op2: Self);
403 fn xor<O: OptInteger>(rop: &mut Integer, op1: O, op2: Self);
404 fn addmul(rop: &mut Integer, op1: &Integer, op2: Self);
405 fn submul(rop: &mut Integer, op1: &Integer, op2: Self);
406 fn mulsub(rop: &mut Integer, op1: &Integer, op2: Self);
407}
408
409pub trait AsLong: Copy {
410 type Long;
411}
412
413macro_rules! as_long {
414 ($Long:ty: $($Prim:ty)*) => { $(
415 impl AsLong for $Prim {
416 type Long = $Long;
417 }
418 )* }
419}
420
421as_long! { c_long: i8 i16 i32 i64 i128 isize }
422as_long! { c_ulong: u8 u16 u32 u64 u128 usize }
423
424macro_rules! forward {
425 (fn $fn:ident() -> $deleg_long:path, $deleg:path) => {
426 #[inline]
427 fn $fn<O: OptInteger>(rop: &mut Integer, op1: O, op2: Self) {
428 if let Some(op2) = op2.checked_as() {
429 $deleg_long(rop, op1, op2);
430 } else {
431 let mut small: MiniInteger = op2.into();
432 $deleg(rop, op1, small.borrow_excl());
433 }
434 }
435 };
436}
437macro_rules! reverse {
438 (fn $fn:ident() -> $deleg_long:path, $deleg:path) => {
439 #[inline]
440 fn $fn<O: OptInteger>(rop: &mut Integer, op1: Self, op2: O) {
441 if let Some(op1) = op1.checked_as() {
442 $deleg_long(rop, op1, op2);
443 } else {
444 let mut small: MiniInteger = op1.into();
445 $deleg(rop, small.borrow_excl(), op2);
446 }
447 }
448 };
449}
450
451impl<T> PrimOps<c_long> for T
452where
453 T: AsLong<Long = c_long> + CheckedCast<c_long> + Into<MiniInteger>,
454{
455 forward! { fn add() -> xmpz::add_si, xmpz::add }
456 forward! { fn sub() -> xmpz::sub_si, xmpz::sub }
457 reverse! { fn sub_from() -> xmpz::si_sub, xmpz::sub }
458 forward! { fn mul() -> xmpz::mul_si, xmpz::mul }
459 forward! { fn div() -> xmpz::tdiv_q_si, xmpz::tdiv_q }
460 reverse! { fn div_from() -> xmpz::si_tdiv_q, xmpz::tdiv_q }
461 forward! { fn rem() -> xmpz::tdiv_r_si, xmpz::tdiv_r }
462 reverse! { fn rem_from() -> xmpz::si_tdiv_r, xmpz::tdiv_r }
463 forward! { fn and() -> xmpz::and_si, xmpz::and }
464 forward! { fn ior() -> xmpz::ior_si, xmpz::ior }
465 forward! { fn xor() -> xmpz::xor_si, xmpz::xor }
466
467 #[inline]
468 fn addmul(rop: &mut Integer, op1: &Integer, op2: Self) {
469 if let Some(op2) = op2.checked_as() {
470 xmpz::addmul_si(rop, op1, op2);
471 } else {
472 let mut small: MiniInteger = op2.into();
473 xmpz::addmul(rop, op1, small.borrow_excl());
474 }
475 }
476
477 #[inline]
478 fn submul(rop: &mut Integer, op1: &Integer, op2: Self) {
479 if let Some(op2) = op2.checked_as() {
480 xmpz::submul_si(rop, op1, op2);
481 } else {
482 let mut small: MiniInteger = op2.into();
483 xmpz::submul(rop, op1, small.borrow_excl());
484 }
485 }
486
487 #[inline]
488 fn mulsub(rop: &mut Integer, op1: &Integer, op2: Self) {
489 if let Some(op2) = op2.checked_as() {
490 xmpz::mulsub_si(rop, op1, op2);
491 } else {
492 let mut small: MiniInteger = op2.into();
493 xmpz::mulsub(rop, op1, small.borrow_excl());
494 }
495 }
496}
497
498impl<T> PrimOps<c_ulong> for T
499where
500 T: AsLong<Long = c_ulong> + CheckedCast<c_ulong> + Into<MiniInteger>,
501{
502 forward! { fn add() -> xmpz::add_ui, xmpz::add }
503 forward! { fn sub() -> xmpz::sub_ui, xmpz::sub }
504 reverse! { fn sub_from() -> xmpz::ui_sub, xmpz::sub }
505 forward! { fn mul() -> xmpz::mul_ui, xmpz::mul }
506 forward! { fn div() -> xmpz::tdiv_q_ui, xmpz::tdiv_q }
507 reverse! { fn div_from() -> xmpz::ui_tdiv_q, xmpz::tdiv_q }
508 forward! { fn rem() -> xmpz::tdiv_r_ui, xmpz::tdiv_r }
509 reverse! { fn rem_from() -> xmpz::ui_tdiv_r, xmpz::tdiv_r }
510 forward! { fn and() -> xmpz::and_ui, xmpz::and }
511 forward! { fn ior() -> xmpz::ior_ui, xmpz::ior }
512 forward! { fn xor() -> xmpz::xor_ui, xmpz::xor }
513
514 #[inline]
515 fn addmul(rop: &mut Integer, op1: &Integer, op2: Self) {
516 if let Some(op2) = op2.checked_as() {
517 xmpz::addmul_ui(rop, op1, op2);
518 } else {
519 let mut small: MiniInteger = op2.into();
520 xmpz::addmul(rop, op1, small.borrow_excl());
521 }
522 }
523
524 #[inline]
525 fn submul(rop: &mut Integer, op1: &Integer, op2: Self) {
526 if let Some(op2) = op2.checked_as() {
527 xmpz::submul_ui(rop, op1, op2);
528 } else {
529 let mut small: MiniInteger = op2.into();
530 xmpz::submul(rop, op1, small.borrow_excl());
531 }
532 }
533
534 #[inline]
535 fn mulsub(rop: &mut Integer, op1: &Integer, op2: Self) {
536 if let Some(op2) = op2.checked_as() {
537 xmpz::mulsub_ui(rop, op1, op2);
538 } else {
539 let mut small: MiniInteger = op2.into();
540 xmpz::mulsub(rop, op1, small.borrow_excl());
541 }
542 }
543}
544
545impl<T> Sum<T> for Integer
546where
547 Integer: AddAssign<T>,
548{
549 fn sum<I>(iter: I) -> Integer
550 where
551 I: Iterator<Item = T>,
552 {
553 let mut ret = Integer::new();
554 for i in iter {
555 ret.add_assign(i);
556 }
557 ret
558 }
559}
560
561impl<T> Product<T> for Integer
562where
563 Integer: MulAssign<T>,
564{
565 fn product<I>(iter: I) -> Integer
566 where
567 I: Iterator<Item = T>,
568 {
569 let mut ret = Integer::from(1);
570 for i in iter {
571 ret.mul_assign(i);
572 }
573 ret
574 }
575}
576
577#[inline]
578fn rhs_has_more_alloc(lhs: &Integer, rhs: &Integer) -> bool {
579 lhs.inner().alloc < rhs.inner().alloc
580}
581
582#[cfg(test)]
583mod tests {
584 use crate::Integer;
585 use crate::ops::{AddFrom, Pow, SubFrom};
586 use core::ops::{AddAssign, SubAssign};
587
588 macro_rules! test_op {
589 ($lhs:ident $op:tt $rhs:ident) => {
590 let ans = $lhs.clone() $op $rhs.clone();
591 assert_eq!(ans, $lhs.clone() $op $rhs);
592 assert_eq!(ans, $lhs $op $rhs.clone());
593 assert_eq!(ans, Integer::from($lhs $op $rhs));
594 };
595 }
596
597 #[test]
598 fn check_arith() {
599 use crate::tests::{I32, I64, I128, ISIZE, U32, U64, U128, USIZE};
600 let large = [(1, 100), (-11, 200), (33, 150)];
601 let all = (large.iter().map(|&(n, s)| Integer::from(n) << s))
602 .chain(U32.iter().map(|&x| Integer::from(x)))
603 .chain(I32.iter().map(|&x| Integer::from(x)))
604 .chain(U64.iter().map(|&x| Integer::from(x)))
605 .chain(I64.iter().map(|&x| Integer::from(x)))
606 .chain(U128.iter().map(|&x| Integer::from(x)))
607 .chain(I128.iter().map(|&x| Integer::from(x)))
608 .chain(USIZE.iter().map(|&x| Integer::from(x)))
609 .chain(ISIZE.iter().map(|&x| Integer::from(x)))
610 .collect::<Vec<Integer>>();
611
612 for l in &all {
613 for r in &all {
614 test_op!(l + r);
615 test_op!(l - r);
616 test_op!(l * r);
617 if !r.is_zero() {
618 test_op!(l / r);
619 }
620 test_op!(l & r);
621 test_op!(l | r);
622 test_op!(l ^ r);
623 }
624 }
625 }
626
627 macro_rules! check_u_s {
628 ($list:expr, $against:expr) => {
629 for &op in $list {
630 let iop = Integer::from(op);
631 for b in &$against {
632 assert_eq!(b.clone() + op, b.clone() + &iop);
633 assert_eq!(b.clone() - op, b.clone() - &iop);
634 assert_eq!(b.clone() * op, b.clone() * &iop);
635 if op != 0 {
636 assert_eq!(b.clone() / op, b.clone() / &iop);
637 assert_eq!(b.clone() % op, b.clone() % &iop);
638 }
639 assert_eq!(b.clone() & op, b.clone() & &iop);
640 assert_eq!(b.clone() | op, b.clone() | &iop);
641 assert_eq!(b.clone() ^ op, b.clone() ^ &iop);
642 assert_eq!(op + b.clone(), iop.clone() + b);
643 assert_eq!(op - b.clone(), iop.clone() - b);
644 assert_eq!(op * b.clone(), iop.clone() * b);
645 if !b.is_zero() {
646 assert_eq!(op / b.clone(), iop.clone() / b);
647 assert_eq!(op % b.clone(), iop.clone() % b);
648 }
649 assert_eq!(op & b.clone(), iop.clone() & b);
650 assert_eq!(op | b.clone(), iop.clone() | b);
651 assert_eq!(op ^ b.clone(), iop.clone() ^ b);
652 }
653 }
654 };
655 }
656
657 #[test]
658 fn check_arith_u_s() {
659 use crate::tests::{I8, I16, I32, I64, I128, ISIZE, U8, U16, U32, U64, U128, USIZE};
660 let large = [(1, 100), (-11, 200), (33, 150)];
661 let against = (large.iter().map(|&(n, s)| Integer::from(n) << s))
662 .chain(U32.iter().map(|&x| Integer::from(x)))
663 .chain(I32.iter().map(|&x| Integer::from(x)))
664 .chain(U64.iter().map(|&x| Integer::from(x)))
665 .chain(I64.iter().map(|&x| Integer::from(x)))
666 .chain(U128.iter().map(|&x| Integer::from(x)))
667 .chain(I128.iter().map(|&x| Integer::from(x)))
668 .chain(USIZE.iter().map(|&x| Integer::from(x)))
669 .chain(ISIZE.iter().map(|&x| Integer::from(x)))
670 .collect::<Vec<Integer>>();
671
672 check_u_s!(I8, against);
673 check_u_s!(I16, against);
674 check_u_s!(I32, against);
675 check_u_s!(I64, against);
676 check_u_s!(I128, against);
677 check_u_s!(ISIZE, against);
678 check_u_s!(U8, against);
679 check_u_s!(U16, against);
680 check_u_s!(U32, against);
681 check_u_s!(U64, against);
682 check_u_s!(U128, against);
683 check_u_s!(USIZE, against);
684 }
685
686 macro_rules! test_ref_op {
687 ($first:expr, $second:expr) => {
688 assert_eq!(
689 Integer::from($first),
690 $second,
691 "({}) != ({})",
692 stringify!($first),
693 stringify!($second)
694 );
695 };
696 }
697
698 #[test]
699 fn check_ref_op() {
700 let lhs = &Integer::from(0x00ff);
701 let rhs = &Integer::from(0x0f0f);
702 let pu = 30_u32;
703 let pi = -15_i32;
704 test_ref_op!(-lhs, -lhs.clone());
705 test_ref_op!(lhs + rhs, lhs.clone() + rhs);
706 test_ref_op!(lhs - rhs, lhs.clone() - rhs);
707 test_ref_op!(lhs * rhs, lhs.clone() * rhs);
708 test_ref_op!(lhs / rhs, lhs.clone() / rhs);
709 test_ref_op!(lhs % rhs, lhs.clone() % rhs);
710 test_ref_op!(!lhs, !lhs.clone());
711 test_ref_op!(lhs & rhs, lhs.clone() & rhs);
712 test_ref_op!(lhs | rhs, lhs.clone() | rhs);
713 test_ref_op!(lhs ^ rhs, lhs.clone() ^ rhs);
714
715 test_ref_op!(lhs + pu, lhs.clone() + pu);
716 test_ref_op!(lhs - pu, lhs.clone() - pu);
717 test_ref_op!(lhs * pu, lhs.clone() * pu);
718 test_ref_op!(lhs / pu, lhs.clone() / pu);
719 test_ref_op!(lhs % pu, lhs.clone() % pu);
720 test_ref_op!(lhs & pu, lhs.clone() & pu);
721 test_ref_op!(lhs | pu, lhs.clone() | pu);
722 test_ref_op!(lhs ^ pu, lhs.clone() ^ pu);
723 test_ref_op!(lhs << pu, lhs.clone() << pu);
724 test_ref_op!(lhs >> pu, lhs.clone() >> pu);
725 test_ref_op!(lhs.pow(pu), lhs.clone().pow(pu));
726
727 test_ref_op!(lhs + pi, lhs.clone() + pi);
728 test_ref_op!(lhs - pi, lhs.clone() - pi);
729 test_ref_op!(lhs * pi, lhs.clone() * pi);
730 test_ref_op!(lhs / pi, lhs.clone() / pi);
731 test_ref_op!(lhs % pi, lhs.clone() % pi);
732 test_ref_op!(lhs & pi, lhs.clone() & pi);
733 test_ref_op!(lhs | pi, lhs.clone() | pi);
734 test_ref_op!(lhs ^ pi, lhs.clone() ^ pi);
735 test_ref_op!(lhs << pi, lhs.clone() << pi);
736 test_ref_op!(lhs >> pi, lhs.clone() >> pi);
737
738 test_ref_op!(pu + lhs, pu + lhs.clone());
739 test_ref_op!(pu - lhs, pu - lhs.clone());
740 test_ref_op!(pu * lhs, pu * lhs.clone());
741 test_ref_op!(pu / lhs, pu / lhs.clone());
742 test_ref_op!(pu % lhs, pu % lhs.clone());
743 test_ref_op!(pu & lhs, pu & lhs.clone());
744 test_ref_op!(pu | lhs, pu | lhs.clone());
745 test_ref_op!(pu ^ lhs, pu ^ lhs.clone());
746
747 test_ref_op!(pi + lhs, pi + lhs.clone());
748 test_ref_op!(pi - lhs, pi - lhs.clone());
749 test_ref_op!(pi * lhs, pi * lhs.clone());
750 test_ref_op!(pi / lhs, pi / lhs.clone());
751 test_ref_op!(pi % lhs, pi % lhs.clone());
752 test_ref_op!(pi & lhs, pi & lhs.clone());
753 test_ref_op!(pi | lhs, pi | lhs.clone());
754 test_ref_op!(pi ^ lhs, pi ^ lhs.clone());
755 }
756
757 #[test]
758 fn check_shift_u_s() {
759 let pos = &(Integer::from(11) << 100u32);
760 let neg = &(Integer::from(-33) << 50u32);
761
762 assert_eq!(pos.clone() << 10u32, pos.clone() << 10i32);
763 assert_eq!(pos.clone() << 10u32, pos.clone() >> -10i32);
764 assert_eq!(pos.clone() >> 10u32, pos.clone() >> 10i32);
765 assert_eq!(pos.clone() >> 10u32, pos.clone() << -10i32);
766
767 assert_eq!(neg.clone() << 10u32, neg.clone() << 10i32);
768 assert_eq!(neg.clone() << 10u32, neg.clone() >> -10i32);
769 assert_eq!(neg.clone() >> 10u32, neg.clone() >> 10i32);
770 assert_eq!(neg.clone() >> 10u32, neg.clone() << -10i32);
771
772 assert_eq!(pos.clone() << 10u32, pos.clone() << 10usize);
773 assert_eq!(pos.clone() << 10u32, pos.clone() << 10isize);
774 assert_eq!(pos.clone() << 10u32, pos.clone() >> -10isize);
775 assert_eq!(pos.clone() >> 10u32, pos.clone() >> 10usize);
776 assert_eq!(pos.clone() >> 10u32, pos.clone() >> 10isize);
777 assert_eq!(pos.clone() >> 10u32, pos.clone() << -10isize);
778
779 assert_eq!(neg.clone() << 10u32, neg.clone() << 10usize);
780 assert_eq!(neg.clone() << 10u32, neg.clone() << 10isize);
781 assert_eq!(neg.clone() << 10u32, neg.clone() >> -10isize);
782 assert_eq!(neg.clone() >> 10u32, neg.clone() >> 10usize);
783 assert_eq!(neg.clone() >> 10u32, neg.clone() >> 10isize);
784 assert_eq!(neg.clone() >> 10u32, neg.clone() << -10isize);
785
786 assert_eq!(pos.clone() << 10, Integer::from(11) << 110);
787 assert_eq!(pos.clone() << -100, pos.clone() >> 100);
788 assert_eq!(pos.clone() << -100, 11);
789 assert_eq!(neg.clone() << 10, neg.clone() >> -10);
790 assert_eq!(neg.clone() << 10, Integer::from(-33) << 60);
791 assert_eq!(neg.clone() << -100, neg.clone() >> 100);
792 assert_eq!(neg.clone() << -100, -1);
793 }
794
795 fn check_single_addmul<F, T>(i: &mut Integer, j: &mut i32, f: F, u: i32)
796 where
797 F: Fn() -> T,
798 Integer: AddAssign<T> + AddFrom<T>,
799 {
800 *i += f();
801 *j += u;
802 assert_eq!(i, j);
803 i.add_from(f());
804 j.add_from(u);
805 assert_eq!(i, j);
806 }
807
808 fn check_single_submul<F, T>(i: &mut Integer, j: &mut i32, f: F, u: i32)
809 where
810 F: Fn() -> T,
811 Integer: SubAssign<T> + SubFrom<T>,
812 {
813 *i -= f();
814 *j -= u;
815 assert_eq!(i, j);
816 i.sub_from(f());
817 j.sub_from(u);
818 assert_eq!(i, j);
819 }
820
821 #[test]
822 fn check_addmul() {
823 let mut i = Integer::from(10);
824 let mut j = 10i32;
825 let two = Integer::from(2);
826
827 check_single_addmul(&mut i, &mut j, || &two * &two, 2 * 2);
828 check_single_addmul(&mut i, &mut j, || &two * 12u32, 2 * 12);
829 check_single_addmul(&mut i, &mut j, || 13u32 * &two, 13 * 2);
830 check_single_addmul(&mut i, &mut j, || &two * 14i32, 2 * 14);
831 check_single_addmul(&mut i, &mut j, || 15i32 * &two, 15 * 2);
832 check_single_addmul(&mut i, &mut j, || &two * -16i32, 2 * -16);
833 check_single_addmul(&mut i, &mut j, || -17i32 * &two, -17 * 2);
834 }
835
836 #[test]
837 fn check_submul() {
838 let mut i = Integer::from(10);
839 let mut j = 10i32;
840 let two = Integer::from(2);
841
842 check_single_submul(&mut i, &mut j, || &two * &two, 2 * 2);
843 check_single_submul(&mut i, &mut j, || &two * 12u32, 2 * 12);
844 check_single_submul(&mut i, &mut j, || 13u32 * &two, 13 * 2);
845 check_single_submul(&mut i, &mut j, || &two * 14i32, 2 * 14);
846 check_single_submul(&mut i, &mut j, || 15i32 * &two, 15 * 2);
847 check_single_submul(&mut i, &mut j, || &two * -16i32, 2 * -16);
848 check_single_submul(&mut i, &mut j, || -17i32 * &two, -17 * 2);
849 }
850}