gmp/
mpz.rs

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