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; pub 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#[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 pub fn to_str_radix(&self, base: u8) -> String {
160 unsafe {
161 let len = __gmpz_sizeinbase(&self.mpz, base as c_int) as usize + 2;
163
164 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 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 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 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 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 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
513macro_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
530macro_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
775impl<'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