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