use gmp_mpfr_sys::gmp::{self, mpq_t};
use std::mem;
use std::os::raw::{c_long, c_ulong};
pub unsafe fn mpq_inv_check_0(rop: *mut mpq_t, op: *const mpq_t) {
assert_ne!(gmp::mpq_sgn(op), 0, "division by zero");
gmp::mpq_inv(rop, op);
}
pub unsafe fn mpq_mul_2exp_si(rop: *mut mpq_t, op1: *const mpq_t, op2: c_long) {
if op2 >= 0 {
gmp::mpq_mul_2exp(rop, op1, op2 as c_ulong);
} else {
gmp::mpq_div_2exp(rop, op1, op2.wrapping_neg() as c_ulong);
}
}
pub unsafe fn mpq_div_2exp_si(rop: *mut mpq_t, op1: *const mpq_t, op2: c_long) {
if op2 >= 0 {
gmp::mpq_div_2exp(rop, op1, op2 as c_ulong);
} else {
gmp::mpq_mul_2exp(rop, op1, op2.wrapping_neg() as c_ulong);
}
}
pub unsafe fn mpq_pow_ui(rop: *mut mpq_t, op1: *const mpq_t, op2: c_ulong) {
let rop_num = gmp::mpq_numref(rop);
let rop_den = gmp::mpq_denref(rop);
let op1_num = gmp::mpq_numref(op1 as *mut _) as *const _;
let op1_den = gmp::mpq_denref(op1 as *mut _) as *const _;
gmp::mpz_pow_ui(rop_num, op1_num, op2);
gmp::mpz_pow_ui(rop_den, op1_den, op2);
}
pub unsafe fn mpq_pow_si(rop: *mut mpq_t, op1: *const mpq_t, op2: c_long) {
if op2 < 0 {
assert_ne!(gmp::mpq_sgn(op1), 0, "division by zero");
gmp::mpq_inv(rop, op1);
mpq_pow_ui(rop, rop, op2.wrapping_neg() as c_ulong);
} else {
mpq_pow_ui(rop, op1, op2 as c_ulong);
};
}
pub unsafe fn mpq_ceil(rop: *mut gmp::mpz_t, op: *const mpq_t) {
let numref = gmp::mpq_numref(op as *mut _) as *const _;
let denref = gmp::mpq_denref(op as *mut _) as *const _;
if gmp::mpz_cmp_ui(denref, 1) == 0 {
gmp::mpz_set(rop, numref);
} else {
gmp::mpz_tdiv_q(rop, numref, denref);
if gmp::mpz_sgn(numref) > 0 {
gmp::mpz_add_ui(rop, rop, 1);
}
}
}
pub unsafe fn mpq_floor(rop: *mut gmp::mpz_t, op: *const mpq_t) {
let numref = gmp::mpq_numref(op as *mut _) as *const _;
let denref = gmp::mpq_denref(op as *mut _) as *const _;
if gmp::mpz_cmp_ui(denref, 1) == 0 {
gmp::mpz_set(rop, numref);
} else {
gmp::mpz_tdiv_q(rop, numref, denref);
if gmp::mpz_sgn(numref) < 0 {
gmp::mpz_sub_ui(rop, rop, 1);
}
}
}
pub unsafe fn mpq_round(rop: *mut gmp::mpz_t, op: *const mpq_t) {
let numref = gmp::mpq_numref(op as *mut _) as *const _;
let denref = gmp::mpq_denref(op as *mut _) as *const _;
if gmp::mpz_cmp_ui(denref, 1) == 0 {
gmp::mpz_set(rop, numref);
} else {
let bits = ((*denref).size.abs() + 1) * gmp::LIMB_BITS;
let mut rem: gmp::mpz_t = mem::uninitialized();
gmp::mpz_init2(&mut rem, bits as gmp::bitcnt_t);
gmp::mpz_tdiv_qr(rop, &mut rem, numref, denref);
gmp::mpz_abs(&mut rem, &rem);
gmp::mpz_mul_2exp(&mut rem, &rem, 1);
if gmp::mpz_cmp(&rem, denref) >= 0 {
if gmp::mpz_sgn(numref) > 0 {
gmp::mpz_add_ui(rop, rop, 1);
} else {
gmp::mpz_sub_ui(rop, rop, 1);
}
}
gmp::mpz_clear(&mut rem);
}
}
pub unsafe fn mpq_trunc(rop: *mut gmp::mpz_t, op: *const mpq_t) {
let numref = gmp::mpq_numref(op as *mut _) as *const _;
let denref = gmp::mpq_denref(op as *mut _) as *const _;
gmp::mpz_tdiv_q(rop, numref, denref);
}
pub unsafe fn mpq_fract(rop: *mut mpq_t, op: *const mpq_t) {
let r_numref = gmp::mpq_numref(rop);
let r_denref = gmp::mpq_denref(rop);
let numref = gmp::mpq_numref(op as *mut _) as *const _;
let denref = gmp::mpq_denref(op as *mut _) as *const _;
gmp::mpz_tdiv_r(r_numref, numref, denref);
gmp::mpz_set(r_denref, denref);
}
pub unsafe fn mpq_fract_trunc(
fop: *mut mpq_t,
top: *mut gmp::mpz_t,
op: *const mpq_t,
) {
let f_numref = gmp::mpq_numref(fop);
let f_denref = gmp::mpq_denref(fop);
let numref = gmp::mpq_numref(op as *mut _) as *const _;
let denref = gmp::mpq_denref(op as *mut _) as *const _;
gmp::mpz_tdiv_qr(top, f_numref, numref, denref);
gmp::mpz_set(f_denref, denref);
}