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