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; pub 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#[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 pub fn to_str_radix(&self, base: u8) -> String {
208 unsafe {
209 let len = __gmpz_sizeinbase(&self.mpz, base as c_int) as usize + 2;
211
212 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 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 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 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 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 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
561macro_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
578macro_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
823impl<'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