1 // Copyright © 2016–2020 University of Malta
2 
3 // This program is free software: you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public License
5 // as published by the Free Software Foundation, either version 3 of
6 // the License, or (at your option) any later version.
7 //
8 // This program is distributed in the hope that it will be useful, but
9 // WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License and a copy of the GNU General Public License along with
15 // this program. If not, see <https://www.gnu.org/licenses/>.
16 
17 #[cfg(feature = "rand")]
18 use crate::rand::MutRandState;
19 #[cfg(feature = "integer")]
20 use crate::Integer;
21 #[cfg(feature = "rational")]
22 use crate::Rational;
23 use crate::{
24     float::{Round, SmallFloat, Special},
25     misc::{NegAbs, UnwrappedCast},
26     ops::NegAssign,
27     Float,
28 };
29 use az::CheckedAs;
30 use core::{cmp::Ordering, mem::MaybeUninit, ptr::NonNull};
31 use gmp_mpfr_sys::{
32     gmp::{self, limb_t},
33     mpfr::{self, exp_t, mpfr_t, prec_t, rnd_t},
34 };
35 use libc::{c_int, c_long, c_ulong, c_void, intmax_t, uintmax_t};
36 
37 pub trait OptFloat: Copy {
38     const IS_SOME: bool;
mpfr(self) -> *const mpfr_t39     fn mpfr(self) -> *const mpfr_t;
mpfr_or(self, default: *mut mpfr_t) -> *const mpfr_t40     fn mpfr_or(self, default: *mut mpfr_t) -> *const mpfr_t;
unwrap_or<'a>(self, default: &'a mut Float) -> &'a Float where Self: 'a41     fn unwrap_or<'a>(self, default: &'a mut Float) -> &'a Float
42     where
43         Self: 'a;
44 }
45 
46 impl OptFloat for () {
47     const IS_SOME: bool = false;
48     #[inline(always)]
mpfr(self) -> *const mpfr_t49     fn mpfr(self) -> *const mpfr_t {
50         panic!("unwrapping ()");
51     }
52     #[inline(always)]
mpfr_or(self, default: *mut mpfr_t) -> *const mpfr_t53     fn mpfr_or(self, default: *mut mpfr_t) -> *const mpfr_t {
54         default as *const mpfr_t
55     }
56     #[inline(always)]
unwrap_or<'a>(self, default: &'a mut Float) -> &'a Float where Self: 'a,57     fn unwrap_or<'a>(self, default: &'a mut Float) -> &'a Float
58     where
59         Self: 'a,
60     {
61         &*default
62     }
63 }
64 
65 impl OptFloat for &Float {
66     const IS_SOME: bool = true;
67     #[inline(always)]
mpfr(self) -> *const mpfr_t68     fn mpfr(self) -> *const mpfr_t {
69         self.as_raw()
70     }
71     #[inline(always)]
mpfr_or(self, _default: *mut mpfr_t) -> *const mpfr_t72     fn mpfr_or(self, _default: *mut mpfr_t) -> *const mpfr_t {
73         self.as_raw()
74     }
75     #[inline(always)]
unwrap_or<'b>(self, _default: &'b mut Float) -> &'b Float where Self: 'b,76     fn unwrap_or<'b>(self, _default: &'b mut Float) -> &'b Float
77     where
78         Self: 'b,
79     {
80         self
81     }
82 }
83 
84 #[inline]
raw_round(round: Round) -> rnd_t85 pub fn raw_round(round: Round) -> rnd_t {
86     match round {
87         Round::Nearest => rnd_t::RNDN,
88         Round::Zero => rnd_t::RNDZ,
89         Round::Up => rnd_t::RNDU,
90         Round::Down => rnd_t::RNDD,
91         _ => unreachable!(),
92     }
93 }
94 
95 #[inline]
ordering1(ord: c_int) -> Ordering96 pub fn ordering1(ord: c_int) -> Ordering {
97     ord.cmp(&0)
98 }
99 
100 #[inline]
ordering2(ord: c_int) -> (Ordering, Ordering)101 fn ordering2(ord: c_int) -> (Ordering, Ordering) {
102     // ord == first + 4 * second
103     let first = match ord & 3 {
104         2 => -1,
105         0 => 0,
106         1 => 1,
107         _ => unreachable!(),
108     };
109     let second = match ord >> 2 {
110         2 => -1,
111         0 => 0,
112         1 => 1,
113         _ => unreachable!(),
114     };
115     (ordering1(first), ordering1(second))
116 }
117 
118 macro_rules! unsafe_wrap {
119     (fn $fn:ident($($op:ident: $O:ident),* $(; $param:ident: $T:ty)*) -> $deleg:path) => {
120         #[inline]
121         pub fn $fn<$($O: OptFloat),*>(
122             rop: &mut Float,
123             $($op: $O,)*
124             $($param: $T,)*
125             rnd: Round,
126         ) -> Ordering {
127             let rop = rop.as_raw_mut();
128             $(let $op = $op.mpfr_or(rop);)*
129             ordering1(unsafe { $deleg(rop, $($op,)* $($param.into(),)* raw_round(rnd)) })
130         }
131     };
132 }
133 
134 macro_rules! unsafe_wrap0 {
135     (fn $fn:ident($($param:ident: $T:ty),*) -> $deleg:path) => {
136         #[inline]
137         pub fn $fn(rop: &mut Float, $($param: $T,)* rnd: Round) -> Ordering {
138             ordering1(unsafe { $deleg(rop.as_raw_mut(), $($param.into(),)* raw_round(rnd)) })
139         }
140     };
141 }
142 
143 #[inline]
si_pow_ui(rop: &mut Float, base: i32, exponent: u32, rnd: Round) -> Ordering144 pub fn si_pow_ui(rop: &mut Float, base: i32, exponent: u32, rnd: Round) -> Ordering {
145     let (base_neg, base_abs) = base.neg_abs();
146     if !base_neg || (exponent & 1) == 0 {
147         ordering1(unsafe {
148             mpfr::ui_pow_ui(
149                 rop.as_raw_mut(),
150                 base_abs.into(),
151                 exponent.into(),
152                 raw_round(rnd),
153             )
154         })
155     } else {
156         let reverse_rnd = match rnd {
157             Round::Up => Round::Down,
158             Round::Down => Round::Up,
159             unchanged => unchanged,
160         };
161         let reverse_ord = ordering1(unsafe {
162             mpfr::ui_pow_ui(
163                 rop.as_raw_mut(),
164                 base_abs.into(),
165                 exponent.into(),
166                 raw_round(reverse_rnd),
167             )
168         });
169         neg(rop, (), Round::Nearest);
170         reverse_ord.reverse()
171     }
172 }
173 
174 #[inline]
write_new_nan(x: &mut MaybeUninit<Float>, prec: prec_t)175 pub fn write_new_nan(x: &mut MaybeUninit<Float>, prec: prec_t) {
176     // Safety: we can cast pointers to/from Float/mpfr_t as they are repr(transparent).
177     unsafe {
178         let inner_ptr = cast_ptr_mut!(x.as_mut_ptr(), mpfr_t);
179         mpfr::init2(inner_ptr, prec);
180     }
181 }
182 
183 // do not use mpfr::neg for op is () to avoid function call
184 #[inline]
neg<O: OptFloat>(rop: &mut Float, op: O, rnd: Round) -> Ordering185 pub fn neg<O: OptFloat>(rop: &mut Float, op: O, rnd: Round) -> Ordering {
186     if O::IS_SOME {
187         ordering1(unsafe { mpfr::neg(rop.as_raw_mut(), op.mpfr(), raw_round(rnd)) })
188     } else {
189         // Safety: negating the sign of mpfr_t is always sound.
190         unsafe {
191             rop.inner_mut().sign.neg_assign();
192         }
193         if rop.is_nan() {
194             set_nanflag();
195         }
196         Ordering::Equal
197     }
198 }
199 
200 #[inline]
signum<O: OptFloat>(rop: &mut Float, op: O, _rnd: Round) -> Ordering201 pub fn signum<O: OptFloat>(rop: &mut Float, op: O, _rnd: Round) -> Ordering {
202     let rop = rop.as_raw_mut();
203     let op = op.mpfr_or(rop);
204     unsafe {
205         if mpfr::nan_p(op) != 0 {
206             mpfr::set(rop, op, rnd_t::RNDZ);
207         } else if mpfr::signbit(op) != 0 {
208             mpfr::set_si(rop, -1, rnd_t::RNDZ);
209         } else {
210             mpfr::set_si(rop, 1, rnd_t::RNDZ);
211         }
212     }
213     // mpfr_t has a minimum precision of 1, so -1 and 1 are exactly representable
214     Ordering::Equal
215 }
216 
217 #[inline]
recip<O: OptFloat>(rop: &mut Float, op: O, rnd: Round) -> Ordering218 pub fn recip<O: OptFloat>(rop: &mut Float, op: O, rnd: Round) -> Ordering {
219     let rop = rop.as_raw_mut();
220     let op = op.mpfr_or(rop);
221     ordering1(unsafe { mpfr::ui_div(rop, 1, op, raw_round(rnd)) })
222 }
223 
224 #[inline]
jn<O: OptFloat>(rop: &mut Float, op: O, n: i32, rnd: Round) -> Ordering225 pub fn jn<O: OptFloat>(rop: &mut Float, op: O, n: i32, rnd: Round) -> Ordering {
226     let rop = rop.as_raw_mut();
227     let op = op.mpfr_or(rop);
228     ordering1(unsafe { mpfr::jn(rop, n.into(), op, raw_round(rnd)) })
229 }
230 
231 #[inline]
yn<O: OptFloat>(rop: &mut Float, op: O, n: i32, rnd: Round) -> Ordering232 pub fn yn<O: OptFloat>(rop: &mut Float, op: O, n: i32, rnd: Round) -> Ordering {
233     let rop = rop.as_raw_mut();
234     let op = op.mpfr_or(rop);
235     ordering1(unsafe { mpfr::yn(rop, n.into(), op, raw_round(rnd)) })
236 }
237 
238 #[inline]
sin_cos<O: OptFloat>( rop_sin: &mut Float, rop_cos: &mut Float, op: O, rnd: Round, ) -> (Ordering, Ordering)239 pub fn sin_cos<O: OptFloat>(
240     rop_sin: &mut Float,
241     rop_cos: &mut Float,
242     op: O,
243     rnd: Round,
244 ) -> (Ordering, Ordering) {
245     let rop_sin = rop_sin.as_raw_mut();
246     let rop_cos = rop_cos.as_raw_mut();
247     let op = op.mpfr_or(rop_sin);
248     ordering2(unsafe { mpfr::sin_cos(rop_sin, rop_cos, op, raw_round(rnd)) })
249 }
250 
251 #[inline]
sinh_cosh<O: OptFloat>( rop_sin: &mut Float, rop_cos: &mut Float, op: O, rnd: Round, ) -> (Ordering, Ordering)252 pub fn sinh_cosh<O: OptFloat>(
253     rop_sin: &mut Float,
254     rop_cos: &mut Float,
255     op: O,
256     rnd: Round,
257 ) -> (Ordering, Ordering) {
258     let rop_sin = rop_sin.as_raw_mut();
259     let rop_cos = rop_cos.as_raw_mut();
260     let op = op.mpfr_or(rop_sin);
261     ordering2(unsafe { mpfr::sinh_cosh(rop_sin, rop_cos, op, raw_round(rnd)) })
262 }
263 
264 #[inline]
modf<O: OptFloat>( rop_i: &mut Float, rop_f: &mut Float, op: O, rnd: Round, ) -> (Ordering, Ordering)265 pub fn modf<O: OptFloat>(
266     rop_i: &mut Float,
267     rop_f: &mut Float,
268     op: O,
269     rnd: Round,
270 ) -> (Ordering, Ordering) {
271     let rop_i = rop_i.as_raw_mut();
272     let rop_f = rop_f.as_raw_mut();
273     let op = op.mpfr_or(rop_i);
274     ordering2(unsafe { mpfr::modf(rop_i, rop_f, op, raw_round(rnd)) })
275 }
276 
277 #[inline]
lgamma<O: OptFloat>(rop: &mut Float, op: O, rnd: Round) -> (Ordering, Ordering)278 pub fn lgamma<O: OptFloat>(rop: &mut Float, op: O, rnd: Round) -> (Ordering, Ordering) {
279     let mut sign = MaybeUninit::uninit();
280     let rop = rop.as_raw_mut();
281     let op = op.mpfr_or(rop);
282     let ord = ordering1(unsafe { mpfr::lgamma(rop, sign.as_mut_ptr(), op, raw_round(rnd)) });
283     let sign_ord = if (unsafe { sign.assume_init() }) < 0 {
284         Ordering::Less
285     } else {
286         Ordering::Greater
287     };
288     (sign_ord, ord)
289 }
290 
sum<'a, I>(rop: &mut Float, values: I, rnd: Round) -> Ordering where I: Iterator<Item = &'a Float>,291 pub fn sum<'a, I>(rop: &mut Float, values: I, rnd: Round) -> Ordering
292 where
293     I: Iterator<Item = &'a Float>,
294 {
295     let pointers = values.map(Float::as_raw).collect::<Vec<_>>();
296     unsafe { sum_raw(rop.as_raw_mut(), &pointers, rnd) }
297 }
298 
299 // add original value of rop to sum
sum_including_old<'a, I>(rop: &mut Float, values: I, rnd: Round) -> Ordering where I: Iterator<Item = &'a Float>,300 pub fn sum_including_old<'a, I>(rop: &mut Float, values: I, rnd: Round) -> Ordering
301 where
302     I: Iterator<Item = &'a Float>,
303 {
304     let rop = rop.as_raw_mut();
305     let capacity = values.size_hint().0.checked_add(1).expect("overflow");
306     let mut pointers = Vec::with_capacity(capacity);
307     pointers.push(rop as *const mpfr_t);
308     pointers.extend(values.map(Float::as_raw));
309     unsafe { sum_raw(rop, &pointers, rnd) }
310 }
311 
sum_raw(rop: *mut mpfr_t, pointers: &[*const mpfr_t], rnd: Round) -> Ordering312 pub unsafe fn sum_raw(rop: *mut mpfr_t, pointers: &[*const mpfr_t], rnd: Round) -> Ordering {
313     let n = pointers.len().unwrapped_cast();
314     let tab = cast_ptr!(pointers.as_ptr(), *mut mpfr_t);
315     ordering1(mpfr::sum(rop, tab, n, raw_round(rnd)))
316 }
317 
dot<'a, I>(rop: &mut Float, values: I, rnd: Round) -> Ordering where I: Iterator<Item = (&'a Float, &'a Float)>,318 pub fn dot<'a, I>(rop: &mut Float, values: I, rnd: Round) -> Ordering
319 where
320     I: Iterator<Item = (&'a Float, &'a Float)>,
321 {
322     let (pointers_a, pointers_b): (Vec<_>, Vec<_>) =
323         values.map(|(a, b)| (a.as_raw(), b.as_raw())).unzip();
324     unsafe { dot_raw(rop.as_raw_mut(), &pointers_a, &pointers_b, rnd) }
325 }
326 
327 // add original value of rop to dot
dot_including_old<'a, I>(rop: &mut Float, values: I, rnd: Round) -> Ordering where I: Iterator<Item = (&'a Float, &'a Float)>,328 pub fn dot_including_old<'a, I>(rop: &mut Float, values: I, rnd: Round) -> Ordering
329 where
330     I: Iterator<Item = (&'a Float, &'a Float)>,
331 {
332     const LIMB_ONE: limb_t = 1;
333     const LIMB_MSB: limb_t = LIMB_ONE << (gmp::LIMB_BITS - 1);
334     const ONE: mpfr_t = mpfr_t {
335         prec: 1,
336         sign: 1,
337         exp: 1,
338         d: unsafe { NonNull::new_unchecked(&LIMB_MSB as *const limb_t as *mut limb_t) },
339     };
340 
341     let rop = rop.as_raw_mut();
342     let capacity = values.size_hint().0.checked_add(1).expect("overflow");
343     let mut pointers_a = Vec::with_capacity(capacity);
344     let mut pointers_b = Vec::with_capacity(capacity);
345     pointers_a.push(rop as *const mpfr_t);
346     pointers_b.push(&ONE as *const mpfr_t);
347     for a_b in values {
348         pointers_a.push(a_b.0.as_raw());
349         pointers_b.push(a_b.1.as_raw());
350     }
351     unsafe { dot_raw(rop, &pointers_a, &pointers_b, rnd) }
352 }
353 
354 // pointers_a and pointers_b must have same length
dot_raw( rop: *mut mpfr_t, pointers_a: &[*const mpfr_t], pointers_b: &[*const mpfr_t], rnd: Round, ) -> Ordering355 unsafe fn dot_raw(
356     rop: *mut mpfr_t,
357     pointers_a: &[*const mpfr_t],
358     pointers_b: &[*const mpfr_t],
359     rnd: Round,
360 ) -> Ordering {
361     debug_assert_eq!(pointers_a.len(), pointers_b.len());
362     let n = pointers_a.len().unwrapped_cast();
363     let a = cast_ptr!(pointers_a.as_ptr(), *mut mpfr_t);
364     let b = cast_ptr!(pointers_b.as_ptr(), *mut mpfr_t);
365     ordering1(mpfr::dot(rop, a, b, n, raw_round(rnd)))
366 }
367 
368 unsafe_wrap! { fn set(src: O) -> mpfr::set }
369 unsafe_wrap0! { fn set_si(src: c_long) -> mpfr::set_si }
370 unsafe_wrap0! { fn set_sj(src: intmax_t) -> mpfr::set_sj }
371 unsafe_wrap0! { fn set_ui(src: c_ulong) -> mpfr::set_ui }
372 unsafe_wrap0! { fn set_uj(src: uintmax_t) -> mpfr::set_uj }
373 unsafe_wrap0! { fn set_f64(src: f64) -> mpfr::set_d }
374 unsafe_wrap0! { fn prec_round(prec: prec_t) -> mpfr::prec_round }
375 unsafe_wrap! { fn remainder(x: O, y: P) -> mpfr::remainder }
376 unsafe_wrap0! { fn ui_pow_ui(base: u32, exponent: u32) -> mpfr::ui_pow_ui }
377 unsafe_wrap0! { fn ui_2exp(ui: u32, exponent: i32) -> mpfr::set_ui_2exp }
378 unsafe_wrap0! { fn si_2exp(si: i32, exponent: i32) -> mpfr::set_si_2exp }
379 unsafe_wrap! { fn copysign(op1: O, op2: P) -> mpfr::copysign }
380 unsafe_wrap! { fn sqr(op: O) -> mpfr::sqr }
381 unsafe_wrap! { fn sqrt(op: O) -> mpfr::sqrt }
382 unsafe_wrap0! { fn sqrt_ui(u: u32) -> mpfr::sqrt_ui }
383 unsafe_wrap! { fn rec_sqrt(op: O) -> mpfr::rec_sqrt }
384 unsafe_wrap! { fn cbrt(op: O) -> mpfr::cbrt }
385 unsafe_wrap! { fn rootn_ui(op: O; k: u32) -> mpfr::rootn_ui }
386 unsafe_wrap! { fn abs(op: O) -> mpfr::abs }
387 unsafe_wrap! { fn min(op1: O, op2: P) -> mpfr::min }
388 unsafe_wrap! { fn max(op1: O, op2: P) -> mpfr::max }
389 unsafe_wrap! { fn dim(op1: O, op2: P) -> mpfr::dim }
390 unsafe_wrap! { fn log(op: O) -> mpfr::log }
391 unsafe_wrap0! { fn log_ui(u: u32) -> mpfr::log_ui }
392 unsafe_wrap! { fn log2(op: O) -> mpfr::log2 }
393 unsafe_wrap! { fn log10(op: O) -> mpfr::log10 }
394 unsafe_wrap! { fn exp(op: O) -> mpfr::exp }
395 unsafe_wrap! { fn exp2(op: O) -> mpfr::exp2 }
396 unsafe_wrap! { fn exp10(op: O) -> mpfr::exp10 }
397 unsafe_wrap! { fn sin(op: O) -> mpfr::sin }
398 unsafe_wrap! { fn cos(op: O) -> mpfr::cos }
399 unsafe_wrap! { fn tan(op: O) -> mpfr::tan }
400 unsafe_wrap! { fn sec(op: O) -> mpfr::sec }
401 unsafe_wrap! { fn csc(op: O) -> mpfr::csc }
402 unsafe_wrap! { fn cot(op: O) -> mpfr::cot }
403 unsafe_wrap! { fn acos(op: O) -> mpfr::acos }
404 unsafe_wrap! { fn asin(op: O) -> mpfr::asin }
405 unsafe_wrap! { fn atan(op: O) -> mpfr::atan }
406 unsafe_wrap! { fn atan2(y: O, x: P) -> mpfr::atan2 }
407 unsafe_wrap! { fn cosh(op: O) -> mpfr::cosh }
408 unsafe_wrap! { fn sinh(op: O) -> mpfr::sinh }
409 unsafe_wrap! { fn tanh(op: O) -> mpfr::tanh }
410 unsafe_wrap! { fn sech(op: O) -> mpfr::sech }
411 unsafe_wrap! { fn csch(op: O) -> mpfr::csch }
412 unsafe_wrap! { fn coth(op: O) -> mpfr::coth }
413 unsafe_wrap! { fn acosh(op: O) -> mpfr::acosh }
414 unsafe_wrap! { fn asinh(op: O) -> mpfr::asinh }
415 unsafe_wrap! { fn atanh(op: O) -> mpfr::atanh }
416 unsafe_wrap0! { fn fac_ui(n: u32) -> mpfr::fac_ui }
417 unsafe_wrap! { fn log1p(op: O) -> mpfr::log1p }
418 unsafe_wrap! { fn expm1(op: O) -> mpfr::expm1 }
419 unsafe_wrap! { fn eint(op: O) -> mpfr::eint }
420 unsafe_wrap! { fn li2(op: O) -> mpfr::li2 }
421 unsafe_wrap! { fn gamma(op: O) -> mpfr::gamma }
422 unsafe_wrap! { fn gamma_inc(op1: O, op2: P) -> mpfr::gamma_inc }
423 unsafe_wrap! { fn lngamma(op: O) -> mpfr::lngamma }
424 unsafe_wrap! { fn digamma(op: O) -> mpfr::digamma }
425 unsafe_wrap! { fn zeta(op: O) -> mpfr::zeta }
426 unsafe_wrap0! { fn zeta_ui(u: u32) -> mpfr::zeta_ui }
427 unsafe_wrap! { fn erf(op: O) -> mpfr::erf }
428 unsafe_wrap! { fn erfc(op: O) -> mpfr::erfc }
429 unsafe_wrap! { fn j0(op: O) -> mpfr::j0 }
430 unsafe_wrap! { fn j1(op: O) -> mpfr::j1 }
431 unsafe_wrap! { fn y0(op: O) -> mpfr::y0 }
432 unsafe_wrap! { fn y1(op: O) -> mpfr::y1 }
433 unsafe_wrap! { fn agm(op1: O, op2: P) -> mpfr::agm }
434 unsafe_wrap! { fn hypot(x: O, y: P) -> mpfr::hypot }
435 unsafe_wrap! { fn ai(op: O) -> mpfr::ai }
436 unsafe_wrap! { fn rint_ceil(op: O) -> mpfr::rint_ceil }
437 unsafe_wrap! { fn rint_floor(op: O) -> mpfr::rint_floor }
438 unsafe_wrap! { fn rint_round(op: O) -> mpfr::rint_round }
439 unsafe_wrap! { fn rint_roundeven(op: O) -> mpfr::rint_roundeven }
440 unsafe_wrap! { fn rint_trunc(op: O) -> mpfr::rint_trunc }
441 unsafe_wrap! { fn frac(op: O) -> mpfr::frac }
442 unsafe_wrap0! { fn const_log2() -> mpfr::const_log2 }
443 unsafe_wrap0! { fn const_pi() -> mpfr::const_pi }
444 unsafe_wrap0! { fn const_euler() -> mpfr::const_euler }
445 unsafe_wrap0! { fn const_catalan() -> mpfr::const_catalan }
446 unsafe_wrap! { fn fma(op1: O, op2: P, op3: Q) -> mpfr::fma }
447 unsafe_wrap! { fn fms(op1: O, op2: P, op3: Q) -> mpfr::fms }
448 unsafe_wrap! { fn fmma(op1: O, op2: P, op3: Q, op4: R) -> mpfr::fmma }
449 unsafe_wrap! { fn fmms(op1: O, op2: P, op3: Q, op4: R) -> mpfr::fmms }
450 unsafe_wrap! { fn add(op1: O, op2: P) -> mpfr::add }
451 unsafe_wrap! { fn sub(op1: O, op2: P) -> mpfr::sub }
452 unsafe_wrap! { fn mul(op1: O, op2: P) -> mpfr::mul }
453 unsafe_wrap! { fn div(op1: O, op2: P) -> mpfr::div }
454 unsafe_wrap! { fn fmod(op1: O, op2: P) -> mpfr::fmod }
455 unsafe_wrap! { fn pow(op1: O, op2: P) -> mpfr::pow }
456 unsafe_wrap! { fn add_si(op1: O; op2: c_long) -> mpfr::add_si }
457 unsafe_wrap! { fn sub_si(op1: O; op2: c_long) -> mpfr::sub_si }
458 unsafe_wrap! { fn mul_si(op1: O; op2: c_long) -> mpfr::mul_si }
459 unsafe_wrap! { fn div_si(op1: O; op2: c_long) -> mpfr::div_si }
460 unsafe_wrap! { fn pow_si(op1: O; op2: c_long) -> mpfr::pow_si }
461 unsafe_wrap! { fn add_ui(op1: O; op2: c_ulong) -> mpfr::add_ui }
462 unsafe_wrap! { fn sub_ui(op1: O; op2: c_ulong) -> mpfr::sub_ui }
463 unsafe_wrap! { fn mul_ui(op1: O; op2: c_ulong) -> mpfr::mul_ui }
464 unsafe_wrap! { fn div_ui(op1: O; op2: c_ulong) -> mpfr::div_ui }
465 unsafe_wrap! { fn pow_ui(op1: O; op2: c_ulong) -> mpfr::pow_ui }
466 unsafe_wrap! { fn add_d(op1: O; op2: f64) -> mpfr::add_d }
467 unsafe_wrap! { fn sub_d(op1: O; op2: f64) -> mpfr::sub_d }
468 unsafe_wrap! { fn mul_d(op1: O; op2: f64) -> mpfr::mul_d }
469 unsafe_wrap! { fn div_d(op1: O; op2: f64) -> mpfr::div_d }
470 unsafe_wrap! { fn shl_i32(op1: O; op2: i32) -> mpfr::mul_2si }
471 unsafe_wrap! { fn shr_i32(op1: O; op2: i32) -> mpfr::div_2si }
472 unsafe_wrap! { fn shl_u32(op1: O; op2: u32) -> mpfr::mul_2ui }
473 unsafe_wrap! { fn shr_u32(op1: O; op2: u32) -> mpfr::div_2ui }
474 
475 #[inline]
check_range(x: &mut Float, dir: Ordering, rnd: Round) -> Ordering476 pub fn check_range(x: &mut Float, dir: Ordering, rnd: Round) -> Ordering {
477     let dir = match dir {
478         Ordering::Less => -1,
479         Ordering::Equal => 0,
480         Ordering::Greater => 1,
481     };
482     ordering1(unsafe { mpfr::check_range(x.as_raw_mut(), dir, raw_round(rnd)) })
483 }
484 
485 #[inline]
set_nanflag()486 pub fn set_nanflag() {
487     unsafe {
488         mpfr::set_nanflag();
489     }
490 }
491 
492 #[inline]
set_prec_nan(x: &mut Float, prec: prec_t)493 pub fn set_prec_nan(x: &mut Float, prec: prec_t) {
494     unsafe {
495         mpfr::set_prec(x.as_raw_mut(), prec);
496     }
497 }
498 
499 #[inline]
set_special(x: &mut Float, src: Special)500 pub fn set_special(x: &mut Float, src: Special) {
501     const EXP_MAX: c_long = ((!0 as c_ulong) >> 1) as c_long;
502     const EXP_ZERO: c_long = 0 - EXP_MAX;
503     const EXP_NAN: c_long = 1 - EXP_MAX;
504     const EXP_INF: c_long = 2 - EXP_MAX;
505     // Safety: We do not change inner.d, and we set inner.exp to
506     // indicate a singular number so even if the data at inner.d is
507     // uninitialized, we still won't use it.
508     unsafe {
509         let inner = x.inner_mut();
510         match src {
511             Special::Zero => {
512                 inner.sign = 1;
513                 inner.exp = EXP_ZERO;
514             }
515             Special::NegZero => {
516                 inner.sign = -1;
517                 inner.exp = EXP_ZERO;
518             }
519             Special::Infinity => {
520                 inner.sign = 1;
521                 inner.exp = EXP_INF;
522             }
523             Special::NegInfinity => {
524                 inner.sign = -1;
525                 inner.exp = EXP_INF;
526             }
527             Special::Nan => {
528                 inner.sign = 1;
529                 inner.exp = EXP_NAN;
530             }
531             _ => unreachable!(),
532         }
533     }
534 }
535 
536 #[cfg(feature = "integer")]
537 #[inline]
set_z(dst: &mut Float, src: &Integer, rnd: Round) -> Ordering538 pub fn set_z(dst: &mut Float, src: &Integer, rnd: Round) -> Ordering {
539     ordering1(unsafe { mpfr::set_z(dst.as_raw_mut(), src.as_raw(), raw_round(rnd)) })
540 }
541 
542 #[cfg(feature = "rational")]
543 #[inline]
set_q(dst: &mut Float, src: &Rational, rnd: Round) -> Ordering544 pub fn set_q(dst: &mut Float, src: &Rational, rnd: Round) -> Ordering {
545     ordering1(unsafe { mpfr::set_q(dst.as_raw_mut(), src.as_raw(), raw_round(rnd)) })
546 }
547 
548 #[inline]
set_f32(dst: &mut Float, src: f32, rnd: Round) -> Ordering549 pub fn set_f32(dst: &mut Float, src: f32, rnd: Round) -> Ordering {
550     set_f64(dst, src.into(), rnd)
551 }
552 
553 #[inline]
set_i128(rop: &mut Float, val: i128, rnd: Round) -> Ordering554 pub fn set_i128(rop: &mut Float, val: i128, rnd: Round) -> Ordering {
555     let small = SmallFloat::from(val);
556     set(rop, &*small, rnd)
557 }
558 
559 #[inline]
set_u128(rop: &mut Float, val: u128, rnd: Round) -> Ordering560 pub fn set_u128(rop: &mut Float, val: u128, rnd: Round) -> Ordering {
561     let small = SmallFloat::from(val);
562     set(rop, &*small, rnd)
563 }
564 
565 #[inline]
nexttoward(rop: &mut Float, op: &Float)566 pub fn nexttoward(rop: &mut Float, op: &Float) {
567     unsafe { mpfr::nexttoward(rop.as_raw_mut(), op.as_raw()) }
568 }
569 
570 #[inline]
nextabove(rop: &mut Float)571 pub fn nextabove(rop: &mut Float) {
572     unsafe { mpfr::nextabove(rop.as_raw_mut()) }
573 }
574 
575 #[inline]
nextbelow(rop: &mut Float)576 pub fn nextbelow(rop: &mut Float) {
577     unsafe { mpfr::nextbelow(rop.as_raw_mut()) }
578 }
579 
580 #[inline]
sgn(x: &Float) -> Ordering581 pub fn sgn(x: &Float) -> Ordering {
582     ordering1(unsafe { mpfr::sgn(x.as_raw()) })
583 }
584 
585 #[inline]
get_exp(op: &Float) -> exp_t586 pub fn get_exp(op: &Float) -> exp_t {
587     unsafe { mpfr::get_exp(op.as_raw()) }
588 }
589 
get_f32(op: &Float, rnd: Round) -> f32590 pub fn get_f32(op: &Float, rnd: Round) -> f32 {
591     unsafe {
592         let mut limb: [limb_t; 1] = [0];
593         let mut single = MaybeUninit::<mpfr_t>::uninit();
594         custom_zero(single.as_mut_ptr(), limb.as_mut_ptr(), 24);
595         let mut single = single.assume_init();
596         mpfr::set(&mut single, op.as_raw(), raw_round(rnd));
597         let val = mpfr::get_d(&single, rnd_t::RNDZ);
598         val as f32
599     }
600 }
601 
602 #[inline]
get_f64(op: &Float, rnd: Round) -> f64603 pub fn get_f64(op: &Float, rnd: Round) -> f64 {
604     unsafe { mpfr::get_d(op.as_raw(), raw_round(rnd)) }
605 }
606 
607 #[inline]
get_f64_2exp(op: &Float, rnd: Round) -> (f64, c_long)608 pub fn get_f64_2exp(op: &Float, rnd: Round) -> (f64, c_long) {
609     unsafe {
610         let mut exp = MaybeUninit::uninit();
611         let f = mpfr::get_d_2exp(exp.as_mut_ptr(), op.as_raw(), raw_round(rnd));
612         (f, exp.assume_init())
613     }
614 }
615 
616 #[inline]
get_si(op: &Float, rnd: Round) -> c_long617 pub fn get_si(op: &Float, rnd: Round) -> c_long {
618     unsafe { mpfr::get_si(op.as_raw(), raw_round(rnd)) }
619 }
620 
621 #[inline]
get_ui(op: &Float, rnd: Round) -> c_ulong622 pub fn get_ui(op: &Float, rnd: Round) -> c_ulong {
623     unsafe { mpfr::get_ui(op.as_raw(), raw_round(rnd)) }
624 }
625 
626 #[inline]
get_prec(op: &Float) -> prec_t627 pub fn get_prec(op: &Float) -> prec_t {
628     unsafe { mpfr::get_prec(op.as_raw()) }
629 }
630 
631 #[inline]
get_str_ndigits(b: i32, prec: prec_t) -> usize632 pub fn get_str_ndigits(b: i32, prec: prec_t) -> usize {
633     assert!(2 <= b && b <= 62, "radix out of range");
634     unsafe { mpfr::get_str_ndigits(b.into(), prec) }
635 }
636 
637 #[inline]
cmp(op1: &Float, op2: &Float) -> Ordering638 pub fn cmp(op1: &Float, op2: &Float) -> Ordering {
639     ordering1(unsafe { mpfr::cmp(op1.as_raw(), op2.as_raw()) })
640 }
641 
642 #[inline]
cmpabs(op1: &Float, op2: &Float) -> Ordering643 pub fn cmpabs(op1: &Float, op2: &Float) -> Ordering {
644     ordering1(unsafe { mpfr::cmpabs(op1.as_raw(), op2.as_raw()) })
645 }
646 
647 #[inline]
cmp_si(op1: &Float, op2: c_long) -> Ordering648 pub fn cmp_si(op1: &Float, op2: c_long) -> Ordering {
649     ordering1(unsafe { mpfr::cmp_si(op1.as_raw(), op2) })
650 }
651 
652 #[inline]
cmp_ui(op1: &Float, op2: c_ulong) -> Ordering653 pub fn cmp_ui(op1: &Float, op2: c_ulong) -> Ordering {
654     ordering1(unsafe { mpfr::cmp_ui(op1.as_raw(), op2) })
655 }
656 
657 #[inline]
cmp_i64(op1: &Float, op2: i64) -> Ordering658 pub fn cmp_i64(op1: &Float, op2: i64) -> Ordering {
659     if let Some(op2) = op2.checked_as() {
660         ordering1(unsafe { mpfr::cmp_si(op1.as_raw(), op2) })
661     } else {
662         let small = SmallFloat::from(op2);
663         ordering1(unsafe { mpfr::cmp(op1.as_raw(), small.as_raw()) })
664     }
665 }
666 
667 #[inline]
cmp_u64(op1: &Float, op2: u64) -> Ordering668 pub fn cmp_u64(op1: &Float, op2: u64) -> Ordering {
669     if let Some(op2) = op2.checked_as() {
670         ordering1(unsafe { mpfr::cmp_ui(op1.as_raw(), op2) })
671     } else {
672         let small = SmallFloat::from(op2);
673         ordering1(unsafe { mpfr::cmp(op1.as_raw(), small.as_raw()) })
674     }
675 }
676 
677 #[inline]
cmp_i128(op1: &Float, op2: i128) -> Ordering678 pub fn cmp_i128(op1: &Float, op2: i128) -> Ordering {
679     let small = SmallFloat::from(op2);
680     ordering1(unsafe { mpfr::cmp(op1.as_raw(), small.as_raw()) })
681 }
682 
683 #[inline]
cmp_u128(op1: &Float, op2: u128) -> Ordering684 pub fn cmp_u128(op1: &Float, op2: u128) -> Ordering {
685     let small = SmallFloat::from(op2);
686     ordering1(unsafe { mpfr::cmp(op1.as_raw(), small.as_raw()) })
687 }
688 
689 #[inline]
cmp_f64(op1: &Float, op2: f64) -> Ordering690 pub fn cmp_f64(op1: &Float, op2: f64) -> Ordering {
691     ordering1(unsafe { mpfr::cmp_d(op1.as_raw(), op2) })
692 }
693 
694 #[cfg(feature = "integer")]
695 #[inline]
cmp_z(op1: &Float, op2: &Integer) -> Ordering696 pub fn cmp_z(op1: &Float, op2: &Integer) -> Ordering {
697     ordering1(unsafe { mpfr::cmp_z(op1.as_raw(), op2.as_raw()) })
698 }
699 
700 #[cfg(feature = "rational")]
701 #[inline]
get_q(rop: &mut Rational, op: &Float)702 pub fn get_q(rop: &mut Rational, op: &Float) {
703     unsafe {
704         mpfr::get_q(rop.as_raw_mut(), op.as_raw());
705     }
706 }
707 
708 #[cfg(feature = "rational")]
709 #[inline]
cmp_q(op1: &Float, op2: &Rational) -> Ordering710 pub fn cmp_q(op1: &Float, op2: &Rational) -> Ordering {
711     ordering1(unsafe { mpfr::cmp_q(op1.as_raw(), op2.as_raw()) })
712 }
713 
714 #[inline]
cmp_u32_2exp(op1: &Float, op2: u32, e: i32) -> Ordering715 pub fn cmp_u32_2exp(op1: &Float, op2: u32, e: i32) -> Ordering {
716     ordering1(unsafe { mpfr::cmp_ui_2exp(op1.as_raw(), op2.into(), e.into()) })
717 }
718 
719 #[inline]
cmp_i32_2exp(op1: &Float, op2: i32, e: i32) -> Ordering720 pub fn cmp_i32_2exp(op1: &Float, op2: i32, e: i32) -> Ordering {
721     ordering1(unsafe { mpfr::cmp_si_2exp(op1.as_raw(), op2.into(), e.into()) })
722 }
723 
724 #[inline]
signbit(op: &Float) -> bool725 pub fn signbit(op: &Float) -> bool {
726     (unsafe { mpfr::signbit(op.as_raw()) }) != 0
727 }
728 
729 #[inline]
equal_p(op1: &Float, op2: &Float) -> bool730 pub fn equal_p(op1: &Float, op2: &Float) -> bool {
731     (unsafe { mpfr::equal_p(op1.as_raw(), op2.as_raw()) }) != 0
732 }
733 
734 #[inline]
unordered_p(op1: &Float, op2: &Float) -> bool735 pub fn unordered_p(op1: &Float, op2: &Float) -> bool {
736     (unsafe { mpfr::unordered_p(op1.as_raw(), op2.as_raw()) }) != 0
737 }
738 
739 #[inline]
less_p(op1: &Float, op2: &Float) -> bool740 pub fn less_p(op1: &Float, op2: &Float) -> bool {
741     (unsafe { mpfr::less_p(op1.as_raw(), op2.as_raw()) }) != 0
742 }
743 
744 #[inline]
lessequal_p(op1: &Float, op2: &Float) -> bool745 pub fn lessequal_p(op1: &Float, op2: &Float) -> bool {
746     (unsafe { mpfr::lessequal_p(op1.as_raw(), op2.as_raw()) }) != 0
747 }
748 
749 #[inline]
greater_p(op1: &Float, op2: &Float) -> bool750 pub fn greater_p(op1: &Float, op2: &Float) -> bool {
751     (unsafe { mpfr::greater_p(op1.as_raw(), op2.as_raw()) }) != 0
752 }
753 
754 #[inline]
greaterequal_p(op1: &Float, op2: &Float) -> bool755 pub fn greaterequal_p(op1: &Float, op2: &Float) -> bool {
756     (unsafe { mpfr::greaterequal_p(op1.as_raw(), op2.as_raw()) }) != 0
757 }
758 
759 #[inline]
integer_p(op: &Float) -> bool760 pub fn integer_p(op: &Float) -> bool {
761     (unsafe { mpfr::integer_p(op.as_raw()) }) != 0
762 }
763 
764 #[inline]
nan_p(op: &Float) -> bool765 pub fn nan_p(op: &Float) -> bool {
766     (unsafe { mpfr::nan_p(op.as_raw()) }) != 0
767 }
768 
769 #[inline]
inf_p(op: &Float) -> bool770 pub fn inf_p(op: &Float) -> bool {
771     (unsafe { mpfr::inf_p(op.as_raw()) }) != 0
772 }
773 
774 #[inline]
number_p(op: &Float) -> bool775 pub fn number_p(op: &Float) -> bool {
776     (unsafe { mpfr::number_p(op.as_raw()) }) != 0
777 }
778 
779 #[inline]
zero_p(op: &Float) -> bool780 pub fn zero_p(op: &Float) -> bool {
781     (unsafe { mpfr::zero_p(op.as_raw()) }) != 0
782 }
783 
784 #[inline]
regular_p(op: &Float) -> bool785 pub fn regular_p(op: &Float) -> bool {
786     (unsafe { mpfr::regular_p(op.as_raw()) }) != 0
787 }
788 
789 #[inline]
submul<O: OptFloat>( rop: &mut Float, add: O, mul1: &Float, mul2: &Float, rnd: Round, ) -> Ordering790 pub fn submul<O: OptFloat>(
791     rop: &mut Float,
792     add: O,
793     mul1: &Float,
794     mul2: &Float,
795     rnd: Round,
796 ) -> Ordering {
797     let reverse_rnd = match rnd {
798         Round::Up => Round::Down,
799         Round::Down => Round::Up,
800         unchanged => unchanged,
801     };
802     let reverse_ord = fms(rop, mul1, mul2, add, reverse_rnd);
803     if !zero_p(rop) {
804         // the negation here is exact
805         neg(rop, (), Round::Zero);
806     }
807     reverse_ord.reverse()
808 }
809 
810 #[inline]
custom_zero(f: *mut mpfr_t, limbs: *mut limb_t, prec: prec_t)811 pub unsafe fn custom_zero(f: *mut mpfr_t, limbs: *mut limb_t, prec: prec_t) {
812     mpfr::custom_init(limbs as *mut c_void, prec);
813     mpfr::custom_init_set(f, mpfr::ZERO_KIND, 0, prec, limbs as *mut c_void);
814 }
815 
816 #[inline]
custom_regular(f: *mut mpfr_t, limbs: *mut limb_t, exp: exp_t, prec: prec_t)817 pub unsafe fn custom_regular(f: *mut mpfr_t, limbs: *mut limb_t, exp: exp_t, prec: prec_t) {
818     mpfr::custom_init(limbs as *mut c_void, prec);
819     mpfr::custom_init_set(f, mpfr::REGULAR_KIND, exp, prec, limbs as *mut c_void);
820 }
821 
822 #[inline]
custom_special(f: *mut mpfr_t, limbs: *mut limb_t, special: Special, prec: prec_t)823 pub unsafe fn custom_special(f: *mut mpfr_t, limbs: *mut limb_t, special: Special, prec: prec_t) {
824     mpfr::custom_init(limbs as *mut c_void, prec);
825     let kind = match special {
826         Special::Zero => mpfr::ZERO_KIND,
827         Special::NegZero => -mpfr::ZERO_KIND,
828         Special::Infinity => mpfr::INF_KIND,
829         Special::NegInfinity => -mpfr::INF_KIND,
830         Special::Nan => mpfr::NAN_KIND,
831         _ => unreachable!(),
832     };
833     mpfr::custom_init_set(f, kind, 0, prec, limbs as *mut c_void);
834 }
835 
836 pub const EXP_ZERO: mpfr::exp_t = -mpfr::exp_t::max_value();
837 
838 #[inline]
839 #[cfg(feature = "rand")]
urandomb(rop: &mut Float, rng: &mut dyn MutRandState)840 pub fn urandomb(rop: &mut Float, rng: &mut dyn MutRandState) {
841     unsafe {
842         let err = mpfr::urandomb(rop.as_raw_mut(), rng.private().0);
843         assert_eq!(rop.is_nan(), err != 0);
844     }
845 }
846 
847 #[inline]
848 #[cfg(feature = "rand")]
urandom(rop: &mut Float, rng: &mut dyn MutRandState, rnd: Round) -> Ordering849 pub fn urandom(rop: &mut Float, rng: &mut dyn MutRandState, rnd: Round) -> Ordering {
850     ordering1(unsafe { mpfr::urandom(rop.as_raw_mut(), rng.private().0, raw_round(rnd)) })
851 }
852 
853 #[inline]
854 #[cfg(feature = "rand")]
nrandom(rop: &mut Float, rng: &mut dyn MutRandState, rnd: Round) -> Ordering855 pub fn nrandom(rop: &mut Float, rng: &mut dyn MutRandState, rnd: Round) -> Ordering {
856     ordering1(unsafe { mpfr::nrandom(rop.as_raw_mut(), rng.private().0, raw_round(rnd)) })
857 }
858 
859 #[inline]
860 #[cfg(feature = "rand")]
erandom(rop: &mut Float, rng: &mut dyn MutRandState, rnd: Round) -> Ordering861 pub fn erandom(rop: &mut Float, rng: &mut dyn MutRandState, rnd: Round) -> Ordering {
862     ordering1(unsafe { mpfr::erandom(rop.as_raw_mut(), rng.private().0, raw_round(rnd)) })
863 }
864 
865 #[inline]
si_sub<O: OptFloat>(rop: &mut Float, op1: c_long, op2: O, rnd: Round) -> Ordering866 pub fn si_sub<O: OptFloat>(rop: &mut Float, op1: c_long, op2: O, rnd: Round) -> Ordering {
867     let rop = rop.as_raw_mut();
868     let op2 = op2.mpfr_or(rop);
869     ordering1(unsafe { mpfr::si_sub(rop, op1, op2, raw_round(rnd)) })
870 }
871 
872 #[inline]
si_div<O: OptFloat>(rop: &mut Float, op1: c_long, op2: O, rnd: Round) -> Ordering873 pub fn si_div<O: OptFloat>(rop: &mut Float, op1: c_long, op2: O, rnd: Round) -> Ordering {
874     let rop = rop.as_raw_mut();
875     let op2 = op2.mpfr_or(rop);
876     ordering1(unsafe { mpfr::si_div(rop, op1, op2, raw_round(rnd)) })
877 }
878 
879 #[inline]
ui_sub<O: OptFloat>(rop: &mut Float, op1: c_ulong, op2: O, rnd: Round) -> Ordering880 pub fn ui_sub<O: OptFloat>(rop: &mut Float, op1: c_ulong, op2: O, rnd: Round) -> Ordering {
881     let rop = rop.as_raw_mut();
882     let op2 = op2.mpfr_or(rop);
883     ordering1(unsafe { mpfr::ui_sub(rop, op1, op2, raw_round(rnd)) })
884 }
885 
886 #[inline]
ui_div<O: OptFloat>(rop: &mut Float, op1: c_ulong, op2: O, rnd: Round) -> Ordering887 pub fn ui_div<O: OptFloat>(rop: &mut Float, op1: c_ulong, op2: O, rnd: Round) -> Ordering {
888     let rop = rop.as_raw_mut();
889     let op2 = op2.mpfr_or(rop);
890     ordering1(unsafe { mpfr::ui_div(rop, op1, op2, raw_round(rnd)) })
891 }
892 
893 #[inline]
ui_pow<O: OptFloat>(rop: &mut Float, op1: c_ulong, op2: O, rnd: Round) -> Ordering894 pub fn ui_pow<O: OptFloat>(rop: &mut Float, op1: c_ulong, op2: O, rnd: Round) -> Ordering {
895     let rop = rop.as_raw_mut();
896     let op2 = op2.mpfr_or(rop);
897     ordering1(unsafe { mpfr::ui_pow(rop, op1, op2, raw_round(rnd)) })
898 }
899 
900 #[inline]
d_sub<O: OptFloat>(rop: &mut Float, op1: f64, op2: O, rnd: Round) -> Ordering901 pub fn d_sub<O: OptFloat>(rop: &mut Float, op1: f64, op2: O, rnd: Round) -> Ordering {
902     let rop = rop.as_raw_mut();
903     let op2 = op2.mpfr_or(rop);
904     ordering1(unsafe { mpfr::d_sub(rop, op1, op2, raw_round(rnd)) })
905 }
906 
907 #[inline]
d_div<O: OptFloat>(rop: &mut Float, op1: f64, op2: O, rnd: Round) -> Ordering908 pub fn d_div<O: OptFloat>(rop: &mut Float, op1: f64, op2: O, rnd: Round) -> Ordering {
909     let rop = rop.as_raw_mut();
910     let op2 = op2.mpfr_or(rop);
911     ordering1(unsafe { mpfr::d_div(rop, op1, op2, raw_round(rnd)) })
912 }
913 
914 #[inline]
915 #[cfg(feature = "integer")]
add_z<O: OptFloat>(rop: &mut Float, op1: O, op2: &Integer, rnd: Round) -> Ordering916 pub fn add_z<O: OptFloat>(rop: &mut Float, op1: O, op2: &Integer, rnd: Round) -> Ordering {
917     let rop = rop.as_raw_mut();
918     let op1 = op1.mpfr_or(rop);
919     ordering1(unsafe { mpfr::add_z(rop, op1, op2.as_raw(), raw_round(rnd)) })
920 }
921 
922 #[inline]
923 #[cfg(feature = "integer")]
sub_z<O: OptFloat>(rop: &mut Float, op1: O, op2: &Integer, rnd: Round) -> Ordering924 pub fn sub_z<O: OptFloat>(rop: &mut Float, op1: O, op2: &Integer, rnd: Round) -> Ordering {
925     let rop = rop.as_raw_mut();
926     let op1 = op1.mpfr_or(rop);
927     ordering1(unsafe { mpfr::sub_z(rop, op1, op2.as_raw(), raw_round(rnd)) })
928 }
929 
930 #[inline]
931 #[cfg(feature = "integer")]
z_sub<O: OptFloat>(rop: &mut Float, op1: &Integer, op2: O, rnd: Round) -> Ordering932 pub fn z_sub<O: OptFloat>(rop: &mut Float, op1: &Integer, op2: O, rnd: Round) -> Ordering {
933     let rop = rop.as_raw_mut();
934     let op2 = op2.mpfr_or(rop);
935     ordering1(unsafe { mpfr::z_sub(rop, op1.as_raw(), op2, raw_round(rnd)) })
936 }
937 
938 #[inline]
939 #[cfg(feature = "integer")]
mul_z<O: OptFloat>(rop: &mut Float, op1: O, op2: &Integer, rnd: Round) -> Ordering940 pub fn mul_z<O: OptFloat>(rop: &mut Float, op1: O, op2: &Integer, rnd: Round) -> Ordering {
941     let rop = rop.as_raw_mut();
942     let op1 = op1.mpfr_or(rop);
943     ordering1(unsafe { mpfr::mul_z(rop, op1, op2.as_raw(), raw_round(rnd)) })
944 }
945 
946 #[inline]
947 #[cfg(feature = "integer")]
div_z<O: OptFloat>(rop: &mut Float, op1: O, op2: &Integer, rnd: Round) -> Ordering948 pub fn div_z<O: OptFloat>(rop: &mut Float, op1: O, op2: &Integer, rnd: Round) -> Ordering {
949     let rop = rop.as_raw_mut();
950     let op1 = op1.mpfr_or(rop);
951     ordering1(unsafe { mpfr::div_z(rop, op1, op2.as_raw(), raw_round(rnd)) })
952 }
953 
954 #[cfg(feature = "integer")]
z_div<O: OptFloat>(rop: &mut Float, op1: &Integer, op2: O, rnd: Round) -> Ordering955 pub fn z_div<O: OptFloat>(rop: &mut Float, op1: &Integer, op2: O, rnd: Round) -> Ordering {
956     if let Some(op1) = op1.to_i32() {
957         si_div(rop, op1.into(), op2, rnd)
958     } else {
959         let op1 = Float::with_val(op1.significant_bits(), op1);
960         div(rop, &op1, op2, rnd)
961     }
962 }
963 
964 #[inline]
965 #[cfg(feature = "integer")]
pow_z<O: OptFloat>(rop: &mut Float, op1: O, op2: &Integer, rnd: Round) -> Ordering966 pub fn pow_z<O: OptFloat>(rop: &mut Float, op1: O, op2: &Integer, rnd: Round) -> Ordering {
967     let rop = rop.as_raw_mut();
968     let op1 = op1.mpfr_or(rop);
969     ordering1(unsafe { mpfr::pow_z(rop, op1, op2.as_raw(), raw_round(rnd)) })
970 }
971 
972 #[inline]
973 #[cfg(feature = "rational")]
add_q<O: OptFloat>(rop: &mut Float, op1: O, op2: &Rational, rnd: Round) -> Ordering974 pub fn add_q<O: OptFloat>(rop: &mut Float, op1: O, op2: &Rational, rnd: Round) -> Ordering {
975     let rop = rop.as_raw_mut();
976     let op1 = op1.mpfr_or(rop);
977     ordering1(unsafe { mpfr::add_q(rop, op1, op2.as_raw(), raw_round(rnd)) })
978 }
979 
980 #[inline]
981 #[cfg(feature = "rational")]
sub_q<O: OptFloat>(rop: &mut Float, op1: O, op2: &Rational, rnd: Round) -> Ordering982 pub fn sub_q<O: OptFloat>(rop: &mut Float, op1: O, op2: &Rational, rnd: Round) -> Ordering {
983     let rop = rop.as_raw_mut();
984     let op1 = op1.mpfr_or(rop);
985     ordering1(unsafe { mpfr::sub_q(rop, op1, op2.as_raw(), raw_round(rnd)) })
986 }
987 
988 #[cfg(feature = "rational")]
q_sub<O: OptFloat>(rop: &mut Float, op1: &Rational, op2: O, rnd: Round) -> Ordering989 pub fn q_sub<O: OptFloat>(rop: &mut Float, op1: &Rational, op2: O, rnd: Round) -> Ordering {
990     let reverse_rnd = match rnd {
991         Round::Up => Round::Down,
992         Round::Down => Round::Up,
993         unchanged => unchanged,
994     };
995     let reverse_ord = sub_q(rop, op2, op1, reverse_rnd);
996     if !zero_p(rop) {
997         // the negation here is exact
998         neg(rop, (), Round::Zero);
999     }
1000     reverse_ord.reverse()
1001 }
1002 
1003 #[inline]
1004 #[cfg(feature = "rational")]
mul_q<O: OptFloat>(rop: &mut Float, op1: O, op2: &Rational, rnd: Round) -> Ordering1005 pub fn mul_q<O: OptFloat>(rop: &mut Float, op1: O, op2: &Rational, rnd: Round) -> Ordering {
1006     let rop = rop.as_raw_mut();
1007     let op1 = op1.mpfr_or(rop);
1008     ordering1(unsafe { mpfr::mul_q(rop, op1, op2.as_raw(), raw_round(rnd)) })
1009 }
1010 
1011 #[inline]
1012 #[cfg(feature = "rational")]
div_q<O: OptFloat>(rop: &mut Float, op1: O, op2: &Rational, rnd: Round) -> Ordering1013 pub fn div_q<O: OptFloat>(rop: &mut Float, op1: O, op2: &Rational, rnd: Round) -> Ordering {
1014     let rop = rop.as_raw_mut();
1015     let op1 = op1.mpfr_or(rop);
1016     ordering1(unsafe { mpfr::div_q(rop, op1, op2.as_raw(), raw_round(rnd)) })
1017 }
1018 
1019 #[cfg(feature = "rational")]
q_div<O: OptFloat>(rop: &mut Float, op1: &Rational, op2: O, rnd: Round) -> Ordering1020 pub fn q_div<O: OptFloat>(rop: &mut Float, op1: &Rational, op2: O, rnd: Round) -> Ordering {
1021     let denom = {
1022         let op1_den = op1.denom();
1023         let op2 = op2.unwrap_or(rop);
1024         let prec = op1_den
1025             .significant_bits()
1026             .checked_add(op2.prec())
1027             .expect("overflow");
1028         Float::with_val(prec, op1_den * op2)
1029     };
1030     z_div(rop, op1.numer(), &denom, rnd)
1031 }
1032