1use super::mpz::{mpz_struct, Mpz, mpz_ptr, mpz_srcptr};
2use super::mpf::{Mpf, mpf_srcptr};
3use super::sign::Sign;
4use ffi::*;
5use libc::{c_char, c_double, c_int, c_ulong};
6use std::ffi::CString;
7use std::str::FromStr;
8use std::error::Error;
9use std::convert::From;
10use std::mem::uninitialized;
11use std::fmt;
12use std::cmp::Ordering::{self, Greater, Less, Equal};
13use std::ops::{Div, DivAssign, Mul, MulAssign, Add, AddAssign, Sub, SubAssign, Neg};
14use num_traits::{Zero, One};
15
16#[repr(C)]
17pub struct mpq_struct {
18 _mp_num: mpz_struct,
19 _mp_den: mpz_struct
20}
21
22pub type mpq_srcptr = *const mpq_struct;
23pub type mpq_ptr = *mut mpq_struct;
24
25#[link(name = "gmp")]
26extern "C" {
27 fn __gmpq_init(x: mpq_ptr);
28 fn __gmpq_clear(x: mpq_ptr);
29 fn __gmpq_set(rop: mpq_ptr, op: mpq_srcptr);
30 fn __gmpq_set_z(rop: mpq_ptr, op: mpz_srcptr);
31 fn __gmpq_set_ui(rop: mpq_ptr, op1: c_ulong, op2: c_ulong);
32 fn __gmpq_set_d(rop: mpq_ptr, op: c_double);
33 fn __gmpq_set_f(rop: mpq_ptr, op: mpf_srcptr);
34 fn __gmpq_cmp(op1: mpq_srcptr, op2: mpq_srcptr) -> c_int;
35 fn __gmpq_cmp_ui(op1: mpq_srcptr, num2: c_ulong, den2: c_ulong) -> c_int;
36 fn __gmpq_equal(op1: mpq_srcptr, op2: mpq_srcptr) -> c_int;
37 fn __gmpq_add(sum: mpq_ptr, addend1: mpq_srcptr, addend2: mpq_srcptr);
38 fn __gmpq_sub(difference: mpq_ptr, minuend: mpq_srcptr, subtrahend: mpq_srcptr);
39 fn __gmpq_mul(product: mpq_ptr, multiplier: mpq_srcptr, multiplicand: mpq_srcptr);
40 fn __gmpq_div(product: mpq_ptr, multiplier: mpq_srcptr, multiplicand: mpq_srcptr);
41 fn __gmpq_neg(negated_operand: mpq_ptr, operand: mpq_srcptr);
42 fn __gmpq_abs(rop: mpq_ptr, op: mpq_srcptr);
43 fn __gmpq_inv(inverted_number: mpq_ptr, number: mpq_srcptr);
44 fn __gmpq_get_num(numerator: mpz_ptr, rational: mpq_srcptr);
45 fn __gmpq_get_den(denominator: mpz_ptr, rational: mpq_srcptr);
46 fn __gmpq_set_num(rational: mpq_ptr, numerator: mpz_srcptr);
47 fn __gmpq_set_den(rational: mpq_ptr, denominator: mpz_srcptr);
48 fn __gmpq_canonicalize(rational: mpq_ptr);
49 fn __gmpq_get_d(rational: mpq_srcptr) -> c_double;
50 fn __gmpq_set_str(rop: mpq_ptr, str: *const c_char, base: c_int) -> c_int;
51}
52
53pub struct Mpq {
54 mpq: mpq_struct,
55}
56
57unsafe impl Send for Mpq { }
58unsafe impl Sync for Mpq { }
59
60impl Drop for Mpq {
61 fn drop(&mut self) { unsafe { __gmpq_clear(&mut self.mpq) } }
62}
63
64impl Mpq {
65 pub unsafe fn inner(&self) -> mpq_srcptr {
66 &self.mpq
67 }
68
69 pub unsafe fn inner_mut(&mut self) -> mpq_ptr {
70 &mut self.mpq
71 }
72
73 pub fn new() -> Mpq {
74 unsafe {
75 let mut mpq = uninitialized();
76 __gmpq_init(&mut mpq);
77 Mpq { mpq: mpq }
78 }
79 }
80
81 pub fn ratio(num: &Mpz, den: &Mpz) -> Mpq {
82 unsafe {
83 let mut res = Mpq::new();
84 __gmpq_set_num(&mut res.mpq, num.inner());
85 __gmpq_set_den(&mut res.mpq, den.inner());
86 __gmpq_canonicalize(&mut res.mpq);
88 res
89 }
90 }
91
92 pub fn from_str_radix(s: &str, base: u8) -> Result<Mpq, ParseMpqError> {
93 let s = CString::new(s).map_err(|_| ParseMpqError { _priv: () })?;
94 let mut res = Mpq::new();
95 unsafe {
96 assert!(base == 0 || (base >= 2 && base <= 62));
97 let r = __gmpq_set_str(&mut res.mpq, s.as_ptr(), base as c_int);
98
99 if r == 0 {
100 __gmpq_canonicalize(&mut res.mpq);
102 Ok(res)
103 } else {
104 Err(ParseMpqError { _priv: () })
105 }
106 }
107 }
108
109 pub fn set(&mut self, other: &Mpq) {
110 unsafe { __gmpq_set(&mut self.mpq, &other.mpq) }
111 }
112
113 pub fn set_z(&mut self, other: &Mpz) {
114 unsafe { __gmpq_set_z(&mut self.mpq, other.inner()) }
115 }
116
117 pub fn set_d(&mut self, other: f64) {
118 unsafe { __gmpq_set_d(&mut self.mpq, other) }
119 }
120
121 pub fn set_f(&mut self, other: &Mpf) {
122 unsafe { __gmpq_set_f(&mut self.mpq, other.inner()) }
123 }
124
125 pub fn get_num(&self) -> Mpz {
126 unsafe {
127 let mut res = Mpz::new();
128 __gmpq_get_num(res.inner_mut(), &self.mpq);
129 res
130 }
131 }
132
133 pub fn get_den(&self) -> Mpz {
134 unsafe {
135 let mut res = Mpz::new();
136 __gmpq_get_den(res.inner_mut(), &self.mpq);
137 res
138 }
139 }
140
141 pub fn abs(&self) -> Mpq {
142 unsafe {
143 let mut res = Mpq::new();
144 __gmpq_abs(&mut res.mpq, &self.mpq);
145 res
146 }
147 }
148
149 pub fn invert(&self) -> Mpq {
150 unsafe {
151 if self.is_zero() {
152 panic!("divide by zero")
153 }
154
155 let mut res = Mpq::new();
156 __gmpq_inv(&mut res.mpq, &self.mpq);
157 res
158 }
159 }
160
161 pub fn floor(&self) -> Mpz {
162 let mut res = Mpz::new();
163 unsafe {
164 __gmpz_fdiv_q(res.inner_mut(), &self.mpq._mp_num, &self.mpq._mp_den);
165 }
166 res
167 }
168
169 pub fn ceil(&self) -> Mpz {
170 let mut res = Mpz::new();
171 unsafe {
172 __gmpz_cdiv_q(res.inner_mut(), &self.mpq._mp_num, &self.mpq._mp_den);
173 }
174 res
175 }
176
177 pub fn sign(&self) -> Sign {
178 self.get_num().sign()
179 }
180
181 pub fn one() -> Mpq {
182 let mut res = Mpq::new();
183 unsafe { __gmpq_set_ui(&mut res.mpq, 1, 1) }
184 res
185 }
186
187 pub fn zero() -> Mpq { Mpq::new() }
188 pub fn is_zero(&self) -> bool {
189 unsafe { __gmpq_cmp_ui(&self.mpq, 0, 1) == 0 }
190 }
191}
192
193#[derive(Debug)]
194pub struct ParseMpqError {
195 _priv: ()
196}
197
198impl fmt::Display for ParseMpqError {
199 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
200 self.description().fmt(f)
201 }
202}
203
204impl Error for ParseMpqError {
205 fn description(&self) -> &'static str {
206 "invalid rational number"
207 }
208
209 fn cause(&self) -> Option<&'static Error> {
210 None
211 }
212}
213
214impl Clone for Mpq {
215 fn clone(&self) -> Mpq {
216 let mut res = Mpq::new();
217 res.set(self);
218 res
219 }
220}
221
222impl Eq for Mpq { }
223impl PartialEq for Mpq {
224 fn eq(&self, other: &Mpq) -> bool {
225 unsafe { __gmpq_equal(&self.mpq, &other.mpq) != 0 }
226 }
227}
228
229impl Ord for Mpq {
230 fn cmp(&self, other: &Mpq) -> Ordering {
231 let cmp = unsafe { __gmpq_cmp(&self.mpq, &other.mpq) };
232 if cmp == 0 {
233 Equal
234 } else if cmp < 0 {
235 Less
236 } else {
237 Greater
238 }
239 }
240}
241impl PartialOrd for Mpq {
242 fn partial_cmp(&self, other: &Mpq) -> Option<Ordering> {
243 Some(self.cmp(other))
244 }
245}
246
247macro_rules! div_guard {
248 (Div, $what: expr) => {
249 if $what.is_zero() {
250 panic!("divide by zero")
251 }
252 };
253 ($tr: ident, $what: expr) => {}
254}
255
256macro_rules! impl_oper {
257 ($tr: ident, $meth: ident, $tr_assign: ident, $meth_assign: ident, $fun: ident) => {
258 impl $tr<Mpq> for Mpq {
259 type Output = Mpq;
260 #[inline]
261 fn $meth(self, other: Mpq) -> Mpq {
262 self.$meth(&other)
263 }
264 }
265
266 impl<'a> $tr<&'a Mpq> for Mpq {
267 type Output = Mpq;
268 #[inline]
269 fn $meth(mut self, other: &Mpq) -> Mpq {
270 self.$meth_assign(other);
271 self
272 }
273 }
274
275 impl<'a> $tr<Mpq> for &'a Mpq {
276 type Output = Mpq;
277 #[inline]
278 fn $meth(self, mut other: Mpq) -> Mpq {
279 unsafe {
280 div_guard!($tr, other);
281 $fun(&mut other.mpq, &self.mpq, &other.mpq);
282 other
283 }
284 }
285 }
286
287 impl<'a, 'b> $tr<&'a Mpq> for &'b Mpq {
288 type Output = Mpq;
289 fn $meth(self, other: &Mpq) -> Mpq {
290 unsafe {
291 div_guard!($tr, *other);
292 let mut res = Mpq::new();
293 $fun(&mut res.mpq, &self.mpq, &other.mpq);
294 res
295 }
296 }
297 }
298
299 impl<'a> $tr_assign<Mpq> for Mpq {
300 #[inline]
301 fn $meth_assign(&mut self, other: Mpq) {
302 self.$meth_assign(&other)
303 }
304 }
305
306 impl<'a> $tr_assign<&'a Mpq> for Mpq {
307 #[inline]
308 fn $meth_assign(&mut self, other: &Mpq) {
309 unsafe {
310 div_guard!($tr, *other);
311 $fun(&mut self.mpq, &self.mpq, &other.mpq)
312 }
313 }
314 }
315 }
316}
317
318impl_oper!(Add, add, AddAssign, add_assign, __gmpq_add);
319impl_oper!(Sub, sub, SubAssign, sub_assign, __gmpq_sub);
320impl_oper!(Mul, mul, MulAssign, mul_assign, __gmpq_mul);
321impl_oper!(Div, div, DivAssign, div_assign, __gmpq_div);
322
323impl<'b> Neg for &'b Mpq {
324 type Output = Mpq;
325 fn neg(self) -> Mpq {
326 unsafe {
327 let mut res = Mpq::new();
328 __gmpq_neg(&mut res.mpq, &self.mpq);
329 res
330 }
331 }
332}
333
334impl Neg for Mpq {
335 type Output = Mpq;
336 #[inline]
337 fn neg(mut self) -> Mpq {
338 unsafe {
339 __gmpq_neg(&mut self.mpq, &self.mpq);
340 self
341 }
342 }
343}
344
345impl From<Mpq> for f64 {
346 fn from(other: Mpq) -> f64 {
347 f64::from(&other)
348 }
349}
350
351impl<'a> From<&'a Mpq> for f64 {
352 fn from(other: &Mpq) -> f64 {
353 unsafe {
354 __gmpq_get_d(&other.mpq) as f64
355 }
356 }
357}
358
359impl From<Mpz> for Mpq {
360 fn from(other: Mpz) -> Mpq {
361 Mpq::from(&other)
362 }
363}
364
365impl<'a> From<&'a Mpz> for Mpq {
366 fn from(other: &Mpz) -> Mpq {
367 let mut res = Mpq::new();
368 res.set_z(&other);
369 res
370 }
371}
372
373impl From<i64> for Mpq {
374 fn from(other: i64) -> Mpq {
375 From::<Mpz>::from(From::<i64>::from(other))
376 }
377}
378
379impl From<i32> for Mpq {
380 fn from(other: i32) -> Mpq {
381 From::<Mpz>::from(From::<i32>::from(other))
382 }
383}
384
385impl From<u64> for Mpq {
386 fn from(other: u64) -> Mpq {
387 From::<Mpz>::from(From::<u64>::from(other))
388 }
389}
390
391impl From<u32> for Mpq {
392 fn from(other: u32) -> Mpq {
393 From::<Mpz>::from(From::<u32>::from(other))
394 }
395}
396
397impl FromStr for Mpq {
398 type Err = ParseMpqError;
399 fn from_str(s: &str) -> Result<Mpq, ParseMpqError> {
400 Mpq::from_str_radix(s, 10)
401 }
402}
403
404
405impl fmt::Debug for Mpq {
406 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
408 fmt::Display::fmt(&self, f)
409 }
410}
411
412impl fmt::Display for Mpq {
413 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
415 let numer = self.get_num();
416 let denom = self.get_den();
417
418 if denom == From::<i64>::from(1) {
419 write!(f, "{}", numer)
420 } else {
421 write!(f, "{}/{}", numer, denom)
422 }
423 }
424}
425
426impl Zero for Mpq {
427 #[inline]
428 fn zero() -> Mpq {
429 Mpq::zero()
430 }
431
432 #[inline]
433 fn is_zero(&self) -> bool {
434 self.is_zero()
435 }
436}
437
438impl One for Mpq {
439 #[inline]
440 fn one() -> Mpq {
441 Mpq::one()
442 }
443}