1#![allow(unsafe_code)]
2use super::sign::Sign;
3use libc::{c_char, c_double, c_int, c_long, c_ulong, c_void, size_t, strnlen};
4use num_traits::{One, Zero};
5use std::cmp::Ordering::{self, Equal, Greater, Less};
6use std::convert::From;
7use std::error::Error;
8use std::ffi::CString;
9use std::mem::{size_of, uninitialized};
10use std::ops::{
11 Add, AddAssign, BitAnd, BitAndAssign, BitOr, BitOrAssign, BitXor, BitXorAssign, Div, DivAssign,
12 Mul, MulAssign, Neg, Not, Rem, RemAssign, Shl, ShlAssign, Shr, ShrAssign, Sub, SubAssign,
13};
14use std::str::FromStr;
15use std::{fmt, hash};
16use std::{i32, u32, usize};
17
18use super::ffi::*;
19
20#[repr(C)]
21pub struct mpz_struct {
22 _mp_alloc: c_int,
23 _mp_size: c_int,
24 _mp_d: *mut c_void,
25}
26
27pub type mp_limb_t = usize; pub type mp_bitcnt_t = c_ulong;
29pub type mpz_srcptr = *const mpz_struct;
30pub type mpz_ptr = *mut mpz_struct;
31
32#[link(name = "gmp")]
33extern "C" {
34 static __gmp_bits_per_limb: c_int;
35 fn __gmpz_init(x: mpz_ptr);
36 fn __gmpz_init2(x: mpz_ptr, n: mp_bitcnt_t);
37 fn __gmpz_init_set(rop: mpz_ptr, op: mpz_srcptr);
38 fn __gmpz_init_set_ui(rop: mpz_ptr, op: c_ulong);
39 fn __gmpz_init_set_str(rop: mpz_ptr, s: *const c_char, base: c_int) -> c_int;
40 fn __gmpz_clear(x: mpz_ptr);
41 fn __gmpz_realloc2(x: mpz_ptr, n: mp_bitcnt_t);
42 fn __gmpz_set(rop: mpz_ptr, op: mpz_srcptr);
43 fn __gmpz_set_str(rop: mpz_ptr, s: *const c_char, base: c_int) -> c_int;
44 fn __gmpz_get_str(s: *mut c_char, base: c_int, op: mpz_srcptr) -> *mut c_char;
45 fn __gmpz_get_ui(op: mpz_srcptr) -> c_ulong;
46 fn __gmpz_fits_ulong_p(op: mpz_srcptr) -> c_int;
47 fn __gmpz_get_si(op: mpz_srcptr) -> c_ulong;
48 fn __gmpz_get_d(op: mpz_srcptr) -> c_double;
49 fn __gmpz_fits_slong_p(op: mpz_srcptr) -> c_long;
50 fn __gmpz_sizeinbase(op: mpz_srcptr, base: c_int) -> size_t;
51 fn __gmpz_cmp(op1: mpz_srcptr, op2: mpz_srcptr) -> c_int;
52 fn __gmpz_cmp_ui(op1: mpz_srcptr, op2: c_ulong) -> c_int;
53 fn __gmpz_add(rop: mpz_ptr, op1: mpz_srcptr, op2: mpz_srcptr);
54 fn __gmpz_add_ui(rop: mpz_ptr, op1: mpz_srcptr, op2: c_ulong);
55 fn __gmpz_sub(rop: mpz_ptr, op1: mpz_srcptr, op2: mpz_srcptr);
56 fn __gmpz_sub_ui(rop: mpz_ptr, op1: mpz_srcptr, op2: c_ulong);
57 fn __gmpz_ui_sub(rop: mpz_ptr, op1: c_ulong, op2: mpz_srcptr);
58 fn __gmpz_mul(rop: mpz_ptr, op1: mpz_srcptr, op2: mpz_srcptr);
59 fn __gmpz_mul_ui(rop: mpz_ptr, op1: mpz_srcptr, op2: c_ulong);
60 fn __gmpz_mul_si(rop: mpz_ptr, op1: mpz_srcptr, op2: c_long);
61 fn __gmpz_mul_2exp(rop: mpz_ptr, op1: mpz_srcptr, op2: mp_bitcnt_t);
62 fn __gmpz_neg(rop: mpz_ptr, op: mpz_srcptr);
63 fn __gmpz_abs(rop: mpz_ptr, op: mpz_srcptr);
64 fn __gmpz_tdiv_q(q: mpz_ptr, n: mpz_srcptr, d: mpz_srcptr);
65 fn __gmpz_tdiv_r(r: mpz_ptr, n: mpz_srcptr, d: mpz_srcptr);
66 fn __gmpz_tdiv_q_ui(q: mpz_ptr, n: mpz_srcptr, d: c_ulong);
67 fn __gmpz_tdiv_r_ui(r: mpz_ptr, n: mpz_srcptr, d: c_ulong);
68 fn __gmpz_fdiv_r(r: mpz_ptr, n: mpz_srcptr, d: mpz_srcptr);
69 fn __gmpz_fdiv_q_2exp(q: mpz_ptr, n: mpz_srcptr, b: mp_bitcnt_t);
70 fn __gmpz_mod(r: mpz_ptr, n: mpz_srcptr, d: mpz_srcptr);
71 fn __gmpz_divisible_p(n: mpz_srcptr, d: mpz_srcptr) -> c_int;
72 fn __gmpz_and(rop: mpz_ptr, op1: mpz_srcptr, op2: mpz_srcptr);
73 fn __gmpz_ior(rop: mpz_ptr, op1: mpz_srcptr, op2: mpz_srcptr);
74 fn __gmpz_xor(rop: mpz_ptr, op1: mpz_srcptr, op2: mpz_srcptr);
75 fn __gmpz_com(rop: mpz_ptr, op: mpz_srcptr);
76 fn __gmpz_popcount(op: mpz_srcptr) -> mp_bitcnt_t;
77 fn __gmpz_pow_ui(rop: mpz_ptr, base: mpz_srcptr, exp: c_ulong);
78 fn __gmpz_ui_pow_ui(rop: mpz_ptr, base: c_ulong, exp: c_ulong);
79 fn __gmpz_powm(rop: mpz_ptr, base: mpz_srcptr, exp: mpz_srcptr, modulo: mpz_srcptr);
80 fn __gmpz_powm_sec(rop: mpz_ptr, base: mpz_srcptr, exp: mpz_srcptr, modulo: mpz_srcptr);
81 fn __gmpz_hamdist(op1: mpz_srcptr, op2: mpz_srcptr) -> mp_bitcnt_t;
82 fn __gmpz_setbit(rop: mpz_ptr, bit_index: mp_bitcnt_t);
83 fn __gmpz_clrbit(rop: mpz_ptr, bit_index: mp_bitcnt_t);
84 fn __gmpz_combit(rop: mpz_ptr, bit_index: mp_bitcnt_t);
85 fn __gmpz_tstbit(rop: mpz_srcptr, bit_index: mp_bitcnt_t) -> c_int;
86 fn __gmpz_probab_prime_p(n: mpz_srcptr, reps: c_int) -> c_int;
87 fn __gmpz_nextprime(rop: mpz_ptr, op: mpz_srcptr);
88 fn __gmpz_gcd(rop: mpz_ptr, op1: mpz_srcptr, op2: mpz_srcptr);
89 fn __gmpz_gcdext(g: mpz_ptr, s: mpz_ptr, t: mpz_ptr, a: mpz_srcptr, b: mpz_srcptr);
90 fn __gmpz_lcm(rop: mpz_ptr, op1: mpz_srcptr, op2: mpz_srcptr);
91 fn __gmpz_invert(rop: mpz_ptr, op1: mpz_srcptr, op2: mpz_srcptr) -> c_int;
92 fn __gmpz_import(
93 rop: mpz_ptr,
94 count: size_t,
95 order: c_int,
96 size: size_t,
97 endian: c_int,
98 nails: size_t,
99 op: *const c_void,
100 );
101 fn __gmpz_export(
102 rop: *mut c_void,
103 countp: *mut size_t,
104 order: c_int,
105 size: size_t,
106 endian: c_int,
107 nails: size_t,
108 op: mpz_srcptr,
109 );
110 fn __gmpz_root(rop: mpz_ptr, op: mpz_srcptr, n: c_ulong) -> c_int;
111 fn __gmpz_sqrt(rop: mpz_ptr, op: mpz_srcptr);
112 fn __gmpz_millerrabin(n: mpz_srcptr, reps: c_int) -> c_int;
113}
114
115#[repr(transparent)]
116pub struct Mpz {
117 mpz: mpz_struct,
118}
119
120unsafe impl Send for Mpz {}
121unsafe impl Sync for Mpz {}
122
123impl Drop for Mpz {
124 fn drop(&mut self) {
125 unsafe { __gmpz_clear(&mut self.mpz) }
126 }
127}
128
129#[derive(PartialEq)]
131pub enum ProbabPrimeResult {
132 NotPrime,
133 ProbablyPrime,
134 Prime,
135}
136
137impl Mpz {
138 #[inline]
139 pub unsafe fn inner(&self) -> mpz_srcptr {
140 &self.mpz
141 }
142
143 #[inline]
144 pub unsafe fn inner_mut(&mut self) -> mpz_ptr {
145 &mut self.mpz
146 }
147
148 #[inline]
149 pub fn new() -> Mpz {
150 unsafe {
151 let mut mpz = uninitialized();
152 __gmpz_init(&mut mpz);
153 Mpz { mpz }
154 }
155 }
156
157 #[inline]
158 pub fn new_reserve(n: usize) -> Mpz {
159 unsafe {
160 let mut mpz = uninitialized();
161 __gmpz_init2(&mut mpz, n as c_ulong);
162 Mpz { mpz }
163 }
164 }
165
166 #[inline]
167 pub fn reserve(&mut self, n: usize) {
168 if self.bit_length() < n {
169 unsafe { __gmpz_realloc2(&mut self.mpz, n as c_ulong) }
170 }
171 }
172
173 #[inline]
174 pub fn size_in_base(&self, base: u8) -> usize {
175 unsafe { __gmpz_sizeinbase(&self.mpz, base as c_int) as usize }
176 }
177
178 pub fn to_str_radix(&self, base: u8) -> String {
182 unsafe {
183 assert!(base >= 2 && base <= 36, "invalid base");
184 let len = {
186 let len = __gmpz_sizeinbase(&self.mpz, base as c_int) as usize;
187 assert!(usize::MAX - len >= 2, "capacity overflow");
188 len + 2
189 };
190
191 let mut vector: Vec<u8> = Vec::with_capacity(len);
193 __gmpz_get_str(vector.as_mut_ptr() as *mut _, base as c_int, &self.mpz);
194 let string_len = strnlen(vector.as_ptr() as *const _, len);
195 assert!(string_len < len);
196 vector.set_len(string_len);
197 String::from_utf8(vector).expect("GMP returned invalid UTF-8!")
199 }
200 }
201
202 pub fn from_str_radix(s: &str, base: u8) -> Result<Mpz, ParseMpzError> {
203 let s = CString::new(s.to_string()).map_err(|_| ParseMpzError { _priv: () })?;
204 unsafe {
205 assert!(base == 0 || (base >= 2 && base <= 62));
206 let mut mpz = uninitialized();
207 let r = __gmpz_init_set_str(&mut mpz, s.as_ptr(), base as c_int);
208 if r == 0 {
209 Ok(Mpz { mpz })
210 } else {
211 __gmpz_clear(&mut mpz);
212 Err(ParseMpzError { _priv: () })
213 }
214 }
215 }
216
217 #[inline]
218 pub fn set(&mut self, other: &Mpz) {
219 unsafe { __gmpz_set(&mut self.mpz, &other.mpz) }
220 }
221
222 pub fn set_from_str_radix(&mut self, s: &str, base: u8) -> bool {
224 assert!(base == 0 || (base >= 2 && base <= 62));
225 let s = CString::new(s.to_string()).unwrap();
226 unsafe { __gmpz_set_str(&mut self.mpz, s.as_ptr(), base as c_int) == 0 }
227 }
228
229 #[inline]
230 pub fn bit_length(&self) -> usize {
231 unsafe { __gmpz_sizeinbase(&self.mpz, 2) as usize }
232 }
233
234 #[inline]
235 pub fn compl(&self) -> Mpz {
236 unsafe {
237 let mut res = Mpz::new();
238 __gmpz_com(&mut res.mpz, &self.mpz);
239 res
240 }
241 }
242
243 #[inline]
244 pub fn abs(&self) -> Mpz {
245 unsafe {
246 let mut res = Mpz::new();
247 __gmpz_abs(&mut res.mpz, &self.mpz);
248 res
249 }
250 }
251
252 #[inline]
253 pub fn div_floor(&self, other: &Mpz) -> Mpz {
254 unsafe {
255 if other.is_zero() {
256 panic!("divide by zero")
257 }
258
259 let mut res = Mpz::new();
260 __gmpz_fdiv_q(&mut res.mpz, &self.mpz, &other.mpz);
261 res
262 }
263 }
264
265 #[inline]
266 pub fn mod_floor(&self, other: &Mpz) -> Mpz {
267 unsafe {
268 if other.is_zero() {
269 panic!("divide by zero")
270 }
271
272 let mut res = Mpz::new();
273 __gmpz_fdiv_r(&mut res.mpz, &self.mpz, &other.mpz);
274 res
275 }
276 }
277
278 pub fn probab_prime(&self, reps: i32) -> ProbabPrimeResult {
282 match unsafe { __gmpz_probab_prime_p(&self.mpz, reps as c_int) as u8 } {
283 2 => ProbabPrimeResult::Prime,
284 1 => ProbabPrimeResult::ProbablyPrime,
285 0 => ProbabPrimeResult::NotPrime,
286 x => panic!("Undocumented return value {} from __gmpz_probab_prime_p", x),
287 }
288 }
289
290 #[inline]
291 pub fn nextprime(&self) -> Mpz {
292 unsafe {
293 let mut res = Mpz::new();
294 __gmpz_nextprime(&mut res.mpz, &self.mpz);
295 res
296 }
297 }
298
299 #[inline]
300 pub fn gcd(&self, other: &Mpz) -> Mpz {
301 unsafe {
302 let mut res = Mpz::new();
303 __gmpz_gcd(&mut res.mpz, &self.mpz, &other.mpz);
304 res
305 }
306 }
307
308 pub fn gcdext(&self, other: &Mpz) -> (Mpz, Mpz, Mpz) {
310 unsafe {
311 let mut g = Mpz::new();
312 let mut s = Mpz::new();
313 let mut t = Mpz::new();
314 __gmpz_gcdext(&mut g.mpz, &mut s.mpz, &mut t.mpz, &self.mpz, &other.mpz);
315 (g, s, t)
316 }
317 }
318
319 #[inline]
320 pub fn lcm(&self, other: &Mpz) -> Mpz {
321 unsafe {
322 let mut res = Mpz::new();
323 __gmpz_lcm(&mut res.mpz, &self.mpz, &other.mpz);
324 res
325 }
326 }
327
328 #[inline]
329 pub fn is_multiple_of(&self, other: &Mpz) -> bool {
330 unsafe { __gmpz_divisible_p(&self.mpz, &other.mpz) != 0 }
331 }
332
333 #[inline]
334 pub fn divides(&self, other: &Mpz) -> bool {
335 other.is_multiple_of(self)
336 }
337
338 pub fn modulus(&self, modulo: &Mpz) -> Mpz {
339 unsafe {
340 if modulo.is_zero() {
341 panic!("divide by zero")
342 }
343
344 let mut res = Mpz::new();
345 __gmpz_mod(&mut res.mpz, &self.mpz, &modulo.mpz);
346 res
347 }
348 }
349
350 pub fn invert(&self, modulo: &Mpz) -> Option<Mpz> {
352 unsafe {
353 let mut res = Mpz::new();
354 if __gmpz_invert(&mut res.mpz, &self.mpz, &modulo.mpz) == 0 {
355 None
356 } else {
357 Some(res)
358 }
359 }
360 }
361
362 #[inline]
363 pub fn popcount(&self) -> usize {
364 unsafe { __gmpz_popcount(&self.mpz) as usize }
365 }
366
367 #[inline]
368 pub fn pow(&self, exp: u32) -> Mpz {
369 unsafe {
370 let mut res = Mpz::new();
371 __gmpz_pow_ui(&mut res.mpz, &self.mpz, exp as c_ulong);
372 res
373 }
374 }
375
376 #[inline]
377 pub fn powm(&self, exp: &Mpz, modulus: &Mpz) -> Mpz {
378 unsafe {
379 let mut res = Mpz::new();
380 __gmpz_powm(&mut res.mpz, &self.mpz, &exp.mpz, &modulus.mpz);
381 res
382 }
383 }
384
385 #[inline]
386 pub fn powm_sec(&self, exp: &Mpz, modulus: &Mpz) -> Mpz {
387 unsafe {
388 let mut res = Mpz::new();
389 __gmpz_powm_sec(&mut res.mpz, &self.mpz, &exp.mpz, &modulus.mpz);
390 res
391 }
392 }
393
394 #[inline]
395 pub fn ui_pow_ui(x: u32, y: u32) -> Mpz {
396 unsafe {
397 let mut res = Mpz::new();
398 __gmpz_ui_pow_ui(&mut res.mpz, x as c_ulong, y as c_ulong);
399 res
400 }
401 }
402
403 #[inline]
404 pub fn hamdist(&self, other: &Mpz) -> usize {
405 unsafe { __gmpz_hamdist(&self.mpz, &other.mpz) as usize }
406 }
407
408 #[inline]
409 pub fn setbit(&mut self, bit_index: usize) {
410 unsafe { __gmpz_setbit(&mut self.mpz, bit_index as c_ulong) }
411 }
412
413 #[inline]
414 pub fn clrbit(&mut self, bit_index: usize) {
415 unsafe { __gmpz_clrbit(&mut self.mpz, bit_index as c_ulong) }
416 }
417
418 #[inline]
419 pub fn combit(&mut self, bit_index: usize) {
420 unsafe { __gmpz_combit(&mut self.mpz, bit_index as c_ulong) }
421 }
422
423 #[inline]
424 pub fn tstbit(&self, bit_index: usize) -> bool {
425 unsafe { __gmpz_tstbit(&self.mpz, bit_index as c_ulong) == 1 }
426 }
427
428 pub fn root(&self, n: u32) -> Mpz {
429 assert!(self.mpz._mp_size >= 0);
430 unsafe {
431 let mut res = Mpz::new();
432 let _perfect_root = match __gmpz_root(&mut res.mpz, &self.mpz, n as c_ulong) {
433 0 => false,
434 _ => true,
435 };
436 res
438 }
439 }
440
441 pub fn sqrt(&self) -> Mpz {
442 assert!(self.mpz._mp_size >= 0);
443 unsafe {
444 let mut res = Mpz::new();
445 __gmpz_sqrt(&mut res.mpz, &self.mpz);
446 res
447 }
448 }
449
450 pub fn millerrabin(&self, reps: i32) -> i32 {
451 unsafe { __gmpz_millerrabin(&self.mpz, reps as c_int) }
452 }
453
454 pub fn sign(&self) -> Sign {
455 let size = self.mpz._mp_size;
456 if size == 0 {
457 Sign::Zero
458 } else if size > 0 {
459 Sign::Positive
460 } else {
461 Sign::Negative
462 }
463 }
464
465 pub fn one() -> Mpz {
466 unsafe {
467 let mut mpz = uninitialized();
468 __gmpz_init_set_ui(&mut mpz, 1);
469 Mpz { mpz }
470 }
471 }
472
473 pub fn zero() -> Mpz {
474 Mpz::new()
475 }
476
477 pub fn is_zero(&self) -> bool {
478 self.mpz._mp_size == 0
479 }
480}
481
482#[derive(Debug)]
483pub struct ParseMpzError {
484 _priv: (),
485}
486
487impl fmt::Display for ParseMpzError {
488 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
489 f.write_str("invalid integer")
490 }
491}
492
493impl Error for ParseMpzError {}
494
495impl Clone for Mpz {
496 fn clone(&self) -> Mpz {
497 unsafe {
498 let mut mpz = uninitialized();
499 __gmpz_init_set(&mut mpz, &self.mpz);
500 Mpz { mpz }
501 }
502 }
503}
504
505impl Eq for Mpz {}
506
507impl PartialEq for Mpz {
508 fn eq(&self, other: &Mpz) -> bool {
509 unsafe { __gmpz_cmp(&self.mpz, &other.mpz) == 0 }
510 }
511}
512
513impl Ord for Mpz {
514 fn cmp(&self, other: &Mpz) -> Ordering {
515 let cmp = unsafe { __gmpz_cmp(&self.mpz, &other.mpz) };
516 if cmp == 0 {
517 Equal
518 } else if cmp < 0 {
519 Less
520 } else {
521 Greater
522 }
523 }
524}
525
526impl PartialOrd for Mpz {
527 fn partial_cmp(&self, other: &Mpz) -> Option<Ordering> {
528 Some(self.cmp(other))
529 }
530}
531
532macro_rules! div_guard {
536 (Div, $is_zero: expr) => {
537 if $is_zero {
538 panic!("divide by zero")
539 }
540 };
541 (Rem, $is_zero: expr) => {
542 if $is_zero {
543 panic!("divide by zero")
544 }
545 };
546 ($tr: ident, $is_zero: expr) => {};
547}
548
549macro_rules! bit_guard {
552 (u64, $what: ident, $e1: expr, $e2: expr) => {
553 if size_of::<c_ulong>() == 8 || $what <= u32::MAX as u64 {
554 $e1
555 } else {
556 $e2
557 }
558 };
559
560 (i64, $what: ident, $e1: expr, $e2: expr) => {
561 if size_of::<c_long>() == 8 || $what <= i32::MAX as i64 {
562 $e1
563 } else {
564 $e2
565 }
566 };
567
568 (u32, $what: ident, $e1: expr, $e2: expr) => {
569 $e1
570 };
571
572 (i32, $what: ident, $e1: expr, $e2: expr) => {
573 $e1
574 };
575}
576
577macro_rules! impl_oper {
578 ($tr: ident, $meth: ident, $tr_assign: ident, $meth_assign: ident, $fun: ident) => {
579 impl $tr<Mpz> for Mpz {
580 type Output = Mpz;
581 #[inline]
582 fn $meth(self, other: Mpz) -> Mpz {
583 self.$meth(&other)
584 }
585 }
586
587 impl<'a> $tr<&'a Mpz> for Mpz {
588 type Output = Mpz;
589 #[inline]
590 fn $meth(mut self, other: &Mpz) -> Mpz {
591 self.$meth_assign(other);
592 self
593 }
594 }
595
596 impl<'a> $tr<Mpz> for &'a Mpz {
597 type Output = Mpz;
598 #[inline]
599 fn $meth(self, mut other: Mpz) -> Mpz {
600 unsafe {
601 div_guard!($tr, other.is_zero());
602 $fun(&mut other.mpz, &self.mpz, &other.mpz);
603 other
604 }
605 }
606 }
607
608 impl<'a, 'b> $tr<&'b Mpz> for &'a Mpz {
609 type Output = Mpz;
610 fn $meth(self, other: &Mpz) -> Mpz {
611 unsafe {
612 div_guard!($tr, other.is_zero());
613 let mut res = Mpz::new();
614 $fun(&mut res.mpz, &self.mpz, &other.mpz);
615 res
616 }
617 }
618 }
619
620 impl $tr_assign<Mpz> for Mpz {
621 #[inline]
622 fn $meth_assign(&mut self, other: Mpz) {
623 self.$meth_assign(&other)
624 }
625 }
626
627 impl<'a> $tr_assign<&'a Mpz> for Mpz {
628 #[inline]
629 fn $meth_assign(&mut self, other: &Mpz) {
630 unsafe {
631 div_guard!($tr, other.is_zero());
632 $fun(&mut self.mpz, &self.mpz, &other.mpz);
633 }
634 }
635 }
636 };
637
638 (both $num: ident, $cnum: ident, $tr: ident, $meth: ident, $tr_assign: ident, $meth_assign: ident, $fun: ident) => {
639 impl_oper!(normal $num, $cnum, $tr, $meth, $tr_assign, $meth_assign, $fun);
640
641 impl $tr<Mpz> for $num {
642 type Output = Mpz;
643 #[inline]
644 fn $meth(self, mut other: Mpz) -> Mpz {
645 unsafe {
646 bit_guard!($num, self, {
647 $fun(&mut other.mpz, &other.mpz, self as $cnum);
648 other
649 }, other.$meth(Mpz::from(self)))
650 }
651 }
652 }
653
654 impl<'a> $tr<&'a Mpz> for $num {
655 type Output = Mpz;
656 fn $meth(self, other: &'a Mpz) -> Mpz {
657 unsafe {
658 bit_guard!($num, self, {
659 let mut res = Mpz::new();
660 $fun(&mut res.mpz, &other.mpz, self as $cnum);
661 res
662 }, other.$meth(Mpz::from(self)))
663 }
664 }
665 }
666 };
667
668 (normal $num: ident, $cnum: ident, $tr: ident, $meth: ident, $tr_assign: ident, $meth_assign: ident, $fun: ident) => {
669 impl $tr<$num> for Mpz {
670 type Output = Mpz;
671 #[inline]
672 fn $meth(mut self, other: $num) -> Mpz {
673 self.$meth_assign(other);
674 self
675 }
676 }
677
678 impl<'a> $tr<$num> for &'a Mpz {
679 type Output = Mpz;
680 fn $meth(self, other: $num) -> Mpz {
681 unsafe {
682 div_guard!($tr, other == 0);
683 bit_guard!($num, other, {
684 let mut res = Mpz::new();
685 $fun(&mut res.mpz, &self.mpz, other as $cnum);
686 res
687 }, self.$meth(Mpz::from(other)))
688 }
689 }
690 }
691
692 impl $tr_assign<$num> for Mpz {
693 #[inline]
694 fn $meth_assign(&mut self, other: $num) {
695 unsafe {
696 div_guard!($tr, other == 0);
697 bit_guard!($num, other,
698 $fun(&mut self.mpz, &self.mpz, other as $cnum),
699 self.$meth_assign(Mpz::from(other)))
700 }
701 }
702 }
703 };
704
705 (reverse $num: ident, $cnum: ident, $tr: ident, $meth: ident, $fun: ident) => {
706 impl $tr<Mpz> for $num {
707 type Output = Mpz;
708 #[inline]
709 fn $meth(self, mut other: Mpz) -> Mpz {
710 unsafe {
711 bit_guard!($num, self, {
712 $fun(&mut other.mpz, self as $cnum, &other.mpz);
713 other
714 }, Mpz::from(self).$meth(other))
715 }
716 }
717 }
718
719 impl<'a> $tr<&'a Mpz> for $num {
720 type Output = Mpz;
721 fn $meth(self, other: &'a Mpz) -> Mpz {
722 unsafe {
723 bit_guard!($num, self, {
724 let mut res = Mpz::new();
725 $fun(&mut res.mpz, self as $cnum, &other.mpz);
726 res
727 }, Mpz::from(self).$meth(other))
728 }
729 }
730 }
731 };
732
733}
734
735impl_oper!(Add, add, AddAssign, add_assign, __gmpz_add);
736impl_oper!(both u64, c_ulong, Add, add, AddAssign, add_assign, __gmpz_add_ui);
737
738impl_oper!(Sub, sub, SubAssign, sub_assign, __gmpz_sub);
739impl_oper!(normal u64, c_ulong, Sub, sub, SubAssign, sub_assign, __gmpz_sub_ui);
740impl_oper!(reverse u64, c_ulong, Sub, sub, __gmpz_ui_sub);
741
742impl_oper!(Mul, mul, MulAssign, mul_assign, __gmpz_mul);
743impl_oper!(both i64, c_long, Mul, mul, MulAssign, mul_assign, __gmpz_mul_si);
744impl_oper!(both u64, c_ulong, Mul, mul, MulAssign, mul_assign, __gmpz_mul_ui);
745
746impl_oper!(Div, div, DivAssign, div_assign, __gmpz_tdiv_q);
747impl_oper!(normal u64, c_ulong, Div, div, DivAssign, div_assign, __gmpz_tdiv_q_ui);
748
749impl_oper!(Rem, rem, RemAssign, rem_assign, __gmpz_tdiv_r);
750impl_oper!(normal u64, c_ulong, Rem, rem, RemAssign, rem_assign, __gmpz_tdiv_r_ui);
751
752impl<'b> Neg for &'b Mpz {
753 type Output = Mpz;
754 fn neg(self) -> Mpz {
755 unsafe {
756 let mut res = Mpz::new();
757 __gmpz_neg(&mut res.mpz, &self.mpz);
758 res
759 }
760 }
761}
762
763impl Neg for Mpz {
764 type Output = Mpz;
765 #[inline]
766 fn neg(mut self) -> Mpz {
767 unsafe {
768 __gmpz_neg(&mut self.mpz, &self.mpz);
769 self
770 }
771 }
772}
773
774impl<'b> Not for &'b Mpz {
775 type Output = Mpz;
776 fn not(self) -> Mpz {
777 unsafe {
778 let mut res = Mpz::new();
779 __gmpz_com(&mut res.mpz, &self.mpz);
780 res
781 }
782 }
783}
784
785impl Not for Mpz {
786 type Output = Mpz;
787 #[inline]
788 fn not(mut self) -> Mpz {
789 unsafe {
790 __gmpz_com(&mut self.mpz, &self.mpz);
791 self
792 }
793 }
794}
795
796impl<'b> From<&'b Mpz> for Vec<u8> {
798 fn from(other: &Mpz) -> Vec<u8> {
799 unsafe {
800 let bit_size = size_of::<u8>() * 8;
801 let size = (__gmpz_sizeinbase(&other.mpz, 2) + bit_size - 1) / bit_size;
802 let mut result: Vec<u8> = vec![0; size];
803 __gmpz_export(
804 result.as_mut_ptr() as *mut c_void,
805 0 as *mut size_t,
806 1,
807 size_of::<u8>() as size_t,
808 0,
809 0,
810 &other.mpz,
811 );
812 result
813 }
814 }
815}
816
817impl<'b> From<&'b Mpz> for Option<i64> {
818 fn from(other: &Mpz) -> Option<i64> {
819 unsafe {
820 let negative = other.mpz._mp_size < 0;
821 let mut to_export = Mpz::new();
822
823 if negative {
824 __gmpz_com(&mut to_export.mpz, &other.mpz);
825 } else {
826 __gmpz_set(&mut to_export.mpz, &other.mpz);
827 }
828
829 if __gmpz_sizeinbase(&to_export.mpz, 2) <= 63 {
830 let mut result: i64 = 0;
831 __gmpz_export(
832 &mut result as *mut i64 as *mut c_void,
833 0 as *mut size_t,
834 -1,
835 size_of::<i64>() as size_t,
836 0,
837 0,
838 &to_export.mpz,
839 );
840 if negative {
841 Some(result ^ -1i64)
842 } else {
843 Some(result)
844 }
845 } else {
846 return None;
847 }
848 }
849 }
850}
851
852impl<'b> From<&'b Mpz> for Option<u64> {
853 fn from(other: &Mpz) -> Option<u64> {
854 unsafe {
855 if __gmpz_sizeinbase(&other.mpz, 2) <= 64 && other.mpz._mp_size >= 0 {
856 let mut result: u64 = 0;
857 __gmpz_export(
858 &mut result as *mut u64 as *mut c_void,
859 0 as *mut size_t,
860 -1,
861 size_of::<u64>() as size_t,
862 0,
863 0,
864 &other.mpz,
865 );
866 Some(result)
867 } else {
868 None
869 }
870 }
871 }
872}
873
874impl<'a> From<&'a Mpz> for f64 {
875 fn from(other: &Mpz) -> f64 {
876 unsafe { __gmpz_get_d(&other.mpz) as f64 }
877 }
878}
879
880impl<'a> From<&'a [u8]> for Mpz {
881 fn from(other: &'a [u8]) -> Mpz {
882 unsafe {
883 let mut res = Mpz::new();
884 __gmpz_import(
885 &mut res.mpz,
886 other.len(),
887 1,
888 size_of::<u8>() as size_t,
889 0,
890 0,
891 other.as_ptr() as *const c_void,
892 );
893 res
894 }
895 }
896}
897
898impl From<u64> for Mpz {
899 fn from(other: u64) -> Mpz {
900 unsafe {
901 let mut res = Mpz::new();
902 __gmpz_import(
903 &mut res.mpz,
904 1,
905 -1,
906 size_of::<u64>() as size_t,
907 0,
908 0,
909 &other as *const u64 as *const c_void,
910 );
911 res
912 }
913 }
914}
915
916impl From<u32> for Mpz {
917 fn from(other: u32) -> Mpz {
918 unsafe {
919 let mut res = Mpz::new();
920 __gmpz_import(
921 &mut res.mpz,
922 1,
923 -1,
924 size_of::<u32>() as size_t,
925 0,
926 0,
927 &other as *const u32 as *const c_void,
928 );
929 res
930 }
931 }
932}
933
934impl From<i64> for Mpz {
935 fn from(other: i64) -> Mpz {
936 unsafe {
937 let mut res = Mpz::new();
938
939 if other.is_negative() {
940 __gmpz_import(
941 &mut res.mpz,
942 1,
943 -1,
944 size_of::<i64>() as size_t,
945 0,
946 0,
947 &(other ^ -1i64) as *const i64 as *const c_void,
948 );
949 __gmpz_com(&mut res.mpz, &res.mpz);
950 } else {
951 __gmpz_import(
952 &mut res.mpz,
953 1,
954 -1,
955 size_of::<i64>() as size_t,
956 0,
957 0,
958 &other as *const i64 as *const c_void,
959 );
960 }
961 res
962 }
963 }
964}
965
966impl From<i32> for Mpz {
967 fn from(other: i32) -> Mpz {
968 unsafe {
969 let mut res = Mpz::new();
970
971 if other.is_negative() {
972 __gmpz_import(
973 &mut res.mpz,
974 1,
975 -1,
976 size_of::<i32>() as size_t,
977 0,
978 0,
979 &(other ^ -1i32) as *const i32 as *const c_void,
980 );
981 __gmpz_com(&mut res.mpz, &res.mpz);
982 } else {
983 __gmpz_import(
984 &mut res.mpz,
985 1,
986 -1,
987 size_of::<i32>() as size_t,
988 0,
989 0,
990 &other as *const i32 as *const c_void,
991 );
992 }
993 res
994 }
995 }
996}
997
998impl_oper!(BitAnd, bitand, BitAndAssign, bitand_assign, __gmpz_and);
999impl_oper!(BitOr, bitor, BitOrAssign, bitor_assign, __gmpz_ior);
1000impl_oper!(BitXor, bitxor, BitXorAssign, bitxor_assign, __gmpz_xor);
1001
1002impl<'b> Shl<usize> for &'b Mpz {
1003 type Output = Mpz;
1004 fn shl(self, other: usize) -> Mpz {
1005 unsafe {
1006 let mut res = Mpz::new();
1007 __gmpz_mul_2exp(&mut res.mpz, &self.mpz, other as c_ulong);
1008 res
1009 }
1010 }
1011}
1012
1013impl<'b> Shr<usize> for &'b Mpz {
1014 type Output = Mpz;
1015 fn shr(self, other: usize) -> Mpz {
1016 unsafe {
1017 let mut res = Mpz::new();
1018 __gmpz_fdiv_q_2exp(&mut res.mpz, &self.mpz, other as c_ulong);
1019 res
1020 }
1021 }
1022}
1023
1024impl Shl<usize> for Mpz {
1025 type Output = Mpz;
1026 fn shl(self, other: usize) -> Mpz {
1027 unsafe {
1028 let mut res = Mpz::new();
1029 __gmpz_mul_2exp(&mut res.mpz, &self.mpz, other as c_ulong);
1030 res
1031 }
1032 }
1033}
1034
1035impl Shr<usize> for Mpz {
1036 type Output = Mpz;
1037 fn shr(self, other: usize) -> Mpz {
1038 unsafe {
1039 let mut res = Mpz::new();
1040 __gmpz_fdiv_q_2exp(&mut res.mpz, &self.mpz, other as c_ulong);
1041 res
1042 }
1043 }
1044}
1045
1046impl ShlAssign<usize> for Mpz {
1047 fn shl_assign(&mut self, other: usize) {
1048 unsafe {
1049 __gmpz_mul_2exp(&mut self.mpz, &self.mpz, other as c_ulong);
1050 }
1051 }
1052}
1053
1054impl ShrAssign<usize> for Mpz {
1055 fn shr_assign(&mut self, other: usize) {
1056 unsafe {
1057 __gmpz_fdiv_q_2exp(&mut self.mpz, &self.mpz, other as c_ulong);
1058 }
1059 }
1060}
1061
1062impl FromStr for Mpz {
1063 type Err = ParseMpzError;
1064 fn from_str(s: &str) -> Result<Self, Self::Err> {
1065 Mpz::from_str_radix(s, 10)
1066 }
1067}
1068
1069impl fmt::Display for Mpz {
1070 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1071 write!(f, "{}", self.to_str_radix(10))
1072 }
1073}
1074
1075impl fmt::Debug for Mpz {
1076 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1077 write!(f, "{}", self.to_str_radix(10))
1078 }
1079}
1080
1081impl hash::Hash for Mpz {
1082 fn hash<S: hash::Hasher>(&self, state: &mut S) {
1083 unsafe {
1084 for i in 0..self.mpz._mp_size.abs() {
1085 let limb = self.mpz._mp_d as *const mp_limb_t;
1086 let limb = *(limb.offset(i as isize));
1087 limb.hash(state);
1088 }
1089 }
1090 }
1091}
1092
1093impl Zero for Mpz {
1094 #[inline]
1095 fn zero() -> Mpz {
1096 Mpz::zero()
1097 }
1098
1099 #[inline]
1100 fn is_zero(&self) -> bool {
1101 self.is_zero()
1102 }
1103}
1104
1105impl One for Mpz {
1106 #[inline]
1107 fn one() -> Mpz {
1108 Mpz::one()
1109 }
1110}