malachite_float/float/arithmetic/agm.rs
1// Copyright © 2026 Mikhail Hogrefe
2//
3// Uses code adopted from the GNU MPFR Library.
4//
5// Copyright 1999-2024 Free Software Foundation, Inc.
6//
7// Contributed by the AriC and Caramba projects, INRIA.
8//
9// This file is part of Malachite.
10//
11// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
12// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
13// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
14
15use crate::InnerFloat::{Finite, Infinity, NaN, Zero};
16use crate::float::basic::extended::{ExtendedFloat, agm_prec_round_normal_extended};
17use crate::{
18 Float, emulate_float_float_to_float_fn, emulate_rational_rational_to_float_fn,
19 float_either_infinity, float_either_zero, float_infinity, float_nan, float_zero,
20 floor_and_ceiling, test_overflow, test_underflow,
21};
22use alloc::borrow::Cow;
23use core::cmp::Ordering::{self, *};
24use core::cmp::max;
25use core::mem::swap;
26use malachite_base::num::arithmetic::traits::{
27 Agm, AgmAssign, CeilingLogBase2, ShrRoundAssign, Sign, Sqrt, SqrtAssign,
28};
29use malachite_base::num::basic::floats::PrimitiveFloat;
30use malachite_base::num::basic::integers::PrimitiveInt;
31use malachite_base::num::basic::traits::Zero as ZeroTrait;
32use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom, SaturatingFrom};
33use malachite_base::num::logic::traits::SignificantBits;
34use malachite_base::rounding_modes::RoundingMode::{self, *};
35use malachite_nz::natural::arithmetic::float::round::float_can_round;
36use malachite_nz::natural::arithmetic::float::sub::exponent_shift_compare;
37use malachite_nz::platform::Limb;
38use malachite_q::Rational;
39
40// This is mpfr_cmp2 from cmp2.c, MPFR 4.3.0.
41fn cmp2_helper(b: &Float, c: &Float, cancel: &mut u64) -> Ordering {
42 match (b, c) {
43 (
44 Float(Finite {
45 exponent: x_exp,
46 precision: x_prec,
47 significand: x,
48 ..
49 }),
50 Float(Finite {
51 exponent: y_exp,
52 precision: y_prec,
53 significand: y,
54 ..
55 }),
56 ) => {
57 let (o, c) = exponent_shift_compare(
58 x.as_limbs_asc(),
59 i64::from(*x_exp),
60 *x_prec,
61 y.as_limbs_asc(),
62 i64::from(*y_exp),
63 *y_prec,
64 );
65 *cancel = c;
66 o
67 }
68 _ => panic!(),
69 }
70}
71
72// The exponent-scaling divisions below halve signed exponents with truncation toward zero, faithful
73// to MPFR's agm.c and to the bound proofs in the comments; `>>` (floor) would not preserve them.
74#[cfg_attr(dylint_lib = "malachite_lints", allow(mul_div_by_power_of_2_literal))]
75fn agm_prec_round_normal(
76 mut a: Float,
77 mut b: Float,
78 prec: u64,
79 rm: RoundingMode,
80) -> (Float, Ordering) {
81 if a < 0u32 || b < 0u32 {
82 return (float_nan!(), Equal);
83 }
84 let mut working_prec = prec + prec.ceiling_log_base_2() + 15;
85 // b (op2) and a (op1) are the 2 operands but we want b >= a
86 match a.partial_cmp(&b).unwrap() {
87 Equal => return Float::from_float_prec_round(a, prec, rm),
88 Greater => swap(&mut a, &mut b),
89 _ => {}
90 }
91 let mut scaleop = 0;
92 let mut increment = Limb::WIDTH;
93 let mut v;
94 let mut scaleit;
95 loop {
96 let mut err: u64 = 0;
97 let mut u;
98 loop {
99 let u_o;
100 let v_o;
101 (u, u_o) = a.mul_prec_ref_ref(&b, working_prec);
102 (v, v_o) = a.add_prec_ref_ref(&b, working_prec);
103 let u_overflow = test_overflow(&u, u_o);
104 let v_overflow = test_overflow(&v, v_o);
105 if u_overflow || v_overflow || test_underflow(&u, u_o) || test_underflow(&v, v_o) {
106 assert_eq!(scaleop, 0);
107 let e1 = a.get_exponent().unwrap();
108 let e2 = b.get_exponent().unwrap();
109 if u_overflow || v_overflow {
110 // Let's recall that emin <= e1 <= e2 <= emax. There has been an overflow. Thus
111 // e2 >= emax/2. If the mpfr_mul overflowed, then e1 + e2 > emax. If the
112 // mpfr_add overflowed, then e2 = emax. We want: (e1 + scale) + (e2 + scale) <=
113 // emax, i.e. scale <= (emax - e1 - e2) / 2. Let's take scale = min(floor((emax
114 // - e1 - e2) / 2), -1). This is OK, as:
115 // ```
116 // - emin <= scale <= -1.
117 // - e1 + scale >= emin. Indeed:
118 // * If e1 + e2 > emax, then
119 // e1 + scale >= e1 + (emax - e1 - e2) / 2 - 1
120 // >= (emax + e1 - emax) / 2 - 1
121 // >= e1 / 2 - 1 >= emin.
122 // * Otherwise, mpfr_mul didn't overflow, therefore
123 // mpfr_add overflowed and e2 = emax, so that
124 // e1 > emin (see restriction below).
125 // e1 + scale > emin - 1, thus e1 + scale >= emin.
126 // - e2 + scale <= emax, since scale < 0.
127 // ```
128 let e_agm = e1 + e2;
129 if e_agm > Float::MAX_EXPONENT {
130 scaleop = -((e_agm - Float::MAX_EXPONENT + 1) / 2);
131 assert!(scaleop < 0);
132 } else {
133 // The addition necessarily overflowed.
134 assert_eq!(e2, Float::MAX_EXPONENT);
135 // The case where e1 = emin and e2 = emax is not supported here. This would
136 // mean that the precision of e2 would be huge (and possibly not supported
137 // in practice anyway).
138 assert!(e1 > Float::MIN_EXPONENT);
139 // Note: this case is probably impossible to have in practice since we need
140 // e2 = emax, and no overflow in the product. Since the product is >=
141 // 2^(e1+e2-2), it implies e1 + e2 - 2 <= emax, thus e1 <= 2. Now to get an
142 // overflow we need op1 >= 1/2 ulp(op2), which implies that the precision of
143 // op2 should be at least emax-2. On a 64-bit computer this is impossible to
144 // have, and would require a huge amount of memory on a 32-bit computer.
145 scaleop = -1;
146 }
147 } else {
148 // underflow only (in the multiplication)
149 //
150 // We have e1 + e2 <= emin (so, e1 <= e2 <= 0). We want: (e1 + scale) + (e2 +
151 // scale) >= emin + 1, i.e. scale >= (emin + 1 - e1 - e2) / 2. let's take scale
152 // = ceil((emin + 1 - e1 - e2) / 2). This is OK, as: 1. 1 <= scale <= emax. 2.
153 // e1 + scale >= emin + 1 >= emin. 3. e2 + scale <= scale <= emax.
154 assert!(e1 <= e2 && e2 <= 0);
155 scaleop = (Float::MIN_EXPONENT_PLUS_2 - e1 - e2) / 2;
156 assert!(scaleop > 0);
157 }
158 a <<= scaleop;
159 b <<= scaleop;
160 } else {
161 break;
162 }
163 }
164 u.sqrt_assign();
165 v >>= 1u32;
166 scaleit = 0;
167 let mut n: u64 = 1;
168 let mut eq = 0;
169 'mid: while cmp2_helper(&u, &v, &mut eq) != Equal && eq <= working_prec - 2 {
170 let mut uf;
171 let mut vf;
172 loop {
173 vf = (&u + &v) >> 1u32;
174 // See proof in algorithms.tex
175 if eq > working_prec >> 2 {
176 // vf = V(k)
177 let low_p = (working_prec + 1) >> 1;
178 let (mut w, o) = v.sub_prec_ref_ref(&u, low_p); // e = V(k-1)-U(k-1)
179 let mut underflow = test_underflow(&w, o);
180 let o = w.square_round_assign(Nearest); // e = e^2
181 underflow |= test_underflow(&w, o);
182 let o = w.shr_round_assign(4u32, Nearest); // e*= (1/2)^2*1/4
183 underflow |= test_underflow(&w, o);
184 let o = w.div_prec_assign_ref(&vf, low_p); // 1/4*e^2/V(k)
185 underflow |= test_underflow(&w, o);
186 let vf_exp = vf.get_exponent().unwrap();
187 if !underflow {
188 v = vf.sub_prec(w, working_prec).0;
189 // 0 or 1
190 err = u64::exact_from(vf_exp - v.get_exponent().unwrap());
191 break 'mid;
192 }
193 // There has been an underflow because of the cancellation between V(k-1) and
194 // U(k-1). Let's use the conventional method.
195 }
196 // U(k) increases, so that U.V can overflow (but not underflow).
197 uf = &u * &v;
198 // For multiplication using Nearest, is_infinite is sufficient for overflow checking
199 if uf.is_infinite() {
200 let scale2 = -(((u.get_exponent().unwrap() + v.get_exponent().unwrap())
201 - Float::MAX_EXPONENT
202 + 1)
203 / 2);
204 u <<= scale2;
205 v <<= scale2;
206 scaleit += scale2;
207 } else {
208 break;
209 }
210 }
211 u = uf.sqrt();
212 swap(&mut v, &mut vf);
213 n += 1;
214 }
215 // the error on v is bounded by (18n+51) ulps, or twice if there was an exponent loss in the
216 // final subtraction
217 //
218 // 18n+51 should not overflow since n is about log(p)
219 err += (18 * n + 51).ceiling_log_base_2();
220 // we should have n+2 <= 2^(p/4) [see algorithms.tex]
221 if (n + 2).ceiling_log_base_2() <= working_prec >> 2
222 && float_can_round(v.significand_ref().unwrap(), working_prec - err, prec, rm)
223 {
224 break;
225 }
226 working_prec += increment;
227 increment = working_prec >> 1;
228 }
229 v.shr_prec_round(scaleop + scaleit, prec, rm)
230}
231
232// See `agm_prec_round_normal`: the signed exponent halving truncates toward zero on purpose.
233#[cfg_attr(dylint_lib = "malachite_lints", allow(mul_div_by_power_of_2_literal))]
234fn agm_prec_round_ref_ref_normal(
235 a: &Float,
236 b: &Float,
237 prec: u64,
238 rm: RoundingMode,
239) -> (Float, Ordering) {
240 if *a < 0u32 || *b < 0u32 {
241 return (float_nan!(), Equal);
242 }
243 let mut working_prec = prec + prec.ceiling_log_base_2() + 15;
244 let mut a = Cow::Borrowed(a);
245 let mut b = Cow::Borrowed(b);
246 // b (op2) and a (op1) are the 2 operands but we want b >= a
247 match a.partial_cmp(&b).unwrap() {
248 Equal => return Float::from_float_prec_round_ref(a.as_ref(), prec, rm),
249 Greater => swap(&mut a, &mut b),
250 _ => {}
251 }
252 let mut scaleop = 0;
253 let mut increment = Limb::WIDTH;
254 let mut v;
255 let mut scaleit;
256 loop {
257 let mut err: u64 = 0;
258 let mut u;
259 loop {
260 let u_o;
261 let v_o;
262 (u, u_o) = a.mul_prec_ref_ref(&b, working_prec);
263 (v, v_o) = a.add_prec_ref_ref(&b, working_prec);
264 let u_overflow = test_overflow(&u, u_o);
265 let v_overflow = test_overflow(&v, v_o);
266 if u_overflow || v_overflow || test_underflow(&u, u_o) || test_underflow(&v, v_o) {
267 assert_eq!(scaleop, 0);
268 let e1 = a.get_exponent().unwrap();
269 let e2 = b.get_exponent().unwrap();
270 if u_overflow || v_overflow {
271 // Let's recall that emin <= e1 <= e2 <= emax. There has been an overflow. Thus
272 // e2 >= emax/2. If the mpfr_mul overflowed, then e1 + e2 > emax. If the
273 // mpfr_add overflowed, then e2 = emax. We want: (e1 + scale) + (e2 + scale) <=
274 // emax, i.e. scale <= (emax - e1 - e2) / 2. Let's take scale = min(floor((emax
275 // - e1 - e2) / 2), -1). This is OK, as:
276 // ```
277 // - emin <= scale <= -1.
278 // - e1 + scale >= emin. Indeed:
279 // * If e1 + e2 > emax, then
280 // e1 + scale >= e1 + (emax - e1 - e2) / 2 - 1
281 // >= (emax + e1 - emax) / 2 - 1
282 // >= e1 / 2 - 1 >= emin.
283 // * Otherwise, mpfr_mul didn't overflow, therefore
284 // mpfr_add overflowed and e2 = emax, so that
285 // e1 > emin (see restriction below).
286 // e1 + scale > emin - 1, thus e1 + scale >= emin.
287 // - e2 + scale <= emax, since scale < 0.
288 // ```
289 let e_agm = e1 + e2;
290 if e_agm > Float::MAX_EXPONENT {
291 scaleop = -((e_agm - Float::MAX_EXPONENT + 1) / 2);
292 assert!(scaleop < 0);
293 } else {
294 // The addition necessarily overflowed.
295 assert_eq!(e2, Float::MAX_EXPONENT);
296 // The case where e1 = emin and e2 = emax is not supported here. This would
297 // mean that the precision of e2 would be huge (and possibly not supported
298 // in practice anyway).
299 assert!(e1 > Float::MIN_EXPONENT);
300 // Note: this case is probably impossible to have in practice since we need
301 // e2 = emax, and no overflow in the product. Since the product is >=
302 // 2^(e1+e2-2), it implies e1 + e2 - 2 <= emax, thus e1 <= 2. Now to get an
303 // overflow we need op1 >= 1/2 ulp(op2), which implies that the precision of
304 // op2 should be at least emax-2. On a 64-bit computer this is impossible to
305 // have, and would require a huge amount of memory on a 32-bit computer.
306 scaleop = -1;
307 }
308 } else {
309 // underflow only (in the multiplication)
310 //
311 // We have e1 + e2 <= emin (so, e1 <= e2 <= 0). We want: (e1 + scale) + (e2 +
312 // scale) >= emin + 1, i.e. scale >= (emin + 1 - e1 - e2) / 2. let's take scale
313 // = ceil((emin + 1 - e1 - e2) / 2). This is OK, as: 1. 1 <= scale <= emax. 2.
314 // e1 + scale >= emin + 1 >= emin. 3. e2 + scale <= scale <= emax.
315 assert!(e1 <= e2 && e2 <= 0);
316 scaleop = (Float::MIN_EXPONENT_PLUS_2 - e1 - e2) / 2;
317 assert!(scaleop > 0);
318 }
319 *a.to_mut() <<= scaleop;
320 *b.to_mut() <<= scaleop;
321 } else {
322 break;
323 }
324 }
325 u.sqrt_assign();
326 v >>= 1u32;
327 scaleit = 0;
328 let mut n: u64 = 1;
329 let mut eq = 0;
330 'mid: while cmp2_helper(&u, &v, &mut eq) != Equal && eq <= working_prec - 2 {
331 let mut uf;
332 let mut vf;
333 loop {
334 vf = (&u + &v) >> 1u32;
335 // See proof in algorithms.tex
336 if eq > working_prec >> 2 {
337 // vf = V(k)
338 let low_p = (working_prec + 1) >> 1;
339 let (mut w, o) = v.sub_prec_ref_ref(&u, low_p); // e = V(k-1)-U(k-1)
340 let mut underflow = test_underflow(&w, o);
341 let o = w.square_round_assign(Nearest); // e = e^2
342 underflow |= test_underflow(&w, o);
343 let o = w.shr_round_assign(4u32, Nearest); // e*= (1/2)^2*1/4
344 underflow |= test_underflow(&w, o);
345 let o = w.div_prec_assign_ref(&vf, low_p); // 1/4*e^2/V(k)
346 underflow |= test_underflow(&w, o);
347 let vf_exp = vf.get_exponent().unwrap();
348 if !underflow {
349 v = vf.sub_prec(w, working_prec).0;
350 // 0 or 1
351 err = u64::exact_from(vf_exp - v.get_exponent().unwrap());
352 break 'mid;
353 }
354 // There has been an underflow because of the cancellation between V(k-1) and
355 // U(k-1). Let's use the conventional method.
356 }
357 // U(k) increases, so that U.V can overflow (but not underflow).
358 uf = &u * &v;
359 // For multiplication using Nearest, is_infinite is sufficient for overflow checking
360 if uf.is_infinite() {
361 let scale2 = -(((u.get_exponent().unwrap() + v.get_exponent().unwrap())
362 - Float::MAX_EXPONENT
363 + 1)
364 / 2);
365 u <<= scale2;
366 v <<= scale2;
367 scaleit += scale2;
368 } else {
369 break;
370 }
371 }
372 u = uf.sqrt();
373 swap(&mut v, &mut vf);
374 n += 1;
375 }
376 // the error on v is bounded by (18n+51) ulps, or twice if there was an exponent loss in the
377 // final subtraction
378 //
379 // 18n+51 should not overflow since n is about log(p)
380 err += (18 * n + 51).ceiling_log_base_2();
381 // we should have n+2 <= 2^(p/4) [see algorithms.tex]
382 if (n + 2).ceiling_log_base_2() <= working_prec >> 2
383 && float_can_round(v.significand_ref().unwrap(), working_prec - err, prec, rm)
384 {
385 break;
386 }
387 working_prec += increment;
388 increment = working_prec >> 1;
389 }
390 v.shr_prec_round(scaleop + scaleit, prec, rm)
391}
392
393fn agm_rational_helper(
394 x: &Rational,
395 y: &Rational,
396 prec: u64,
397 rm: RoundingMode,
398) -> (Float, Ordering) {
399 let mut working_prec = prec + 10;
400 let mut increment = Limb::WIDTH;
401 loop {
402 let (x_lo, x_o) = Float::from_rational_prec_round_ref(x, working_prec, Floor);
403 let (y_lo, y_o) = Float::from_rational_prec_round_ref(y, working_prec, Floor);
404 if x_o == Equal && y_o == Equal {
405 return agm_prec_round_normal(x_lo, y_lo, prec, rm);
406 }
407 let (x_lo, x_hi) = floor_and_ceiling((x_lo, x_o));
408 let (y_lo, y_hi) = floor_and_ceiling((y_lo, y_o));
409 let (agm_lo, mut o_lo) = agm_prec_round_normal(x_lo, y_lo, prec, rm);
410 let (agm_hi, mut o_hi) = agm_prec_round_normal(x_hi, y_hi, prec, rm);
411 if o_lo == Equal {
412 o_lo = o_hi;
413 }
414 if o_hi == Equal {
415 o_hi = o_lo;
416 }
417 if o_lo == o_hi && agm_lo == agm_hi {
418 return (agm_lo, o_lo);
419 }
420 working_prec += increment;
421 increment = working_prec >> 1;
422 }
423}
424
425fn agm_rational_helper_extended(
426 x: &Rational,
427 y: &Rational,
428 prec: u64,
429 rm: RoundingMode,
430) -> (Float, Ordering) {
431 let mut working_prec = prec + 10;
432 let mut increment = Limb::WIDTH;
433 loop {
434 let (x_lo, x_o) = ExtendedFloat::from_rational_prec_round_ref(x, working_prec, Floor);
435 let (y_lo, y_o) = ExtendedFloat::from_rational_prec_round_ref(y, working_prec, Floor);
436 if x_o == Equal && y_o == Equal {
437 let (agm, o) = agm_prec_round_normal_extended(x_lo, y_lo, prec, rm);
438 return agm.into_float_helper(prec, rm, o);
439 }
440 let (x_lo, x_hi) = crate::float::basic::extended::floor_and_ceiling((x_lo, x_o));
441 let (y_lo, y_hi) = crate::float::basic::extended::floor_and_ceiling((y_lo, y_o));
442 let (agm_lo, mut o_lo) = agm_prec_round_normal_extended(x_lo, y_lo, prec, rm);
443 let (agm_hi, mut o_hi) = agm_prec_round_normal_extended(x_hi, y_hi, prec, rm);
444 if o_lo == Equal {
445 o_lo = o_hi;
446 }
447 if o_hi == Equal {
448 o_hi = o_lo;
449 }
450 if o_lo == o_hi && agm_lo == agm_hi {
451 return agm_lo.into_float_helper(prec, rm, o_lo);
452 }
453 working_prec += increment;
454 increment = working_prec >> 1;
455 }
456}
457
458impl Float {
459 /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, rounding the result to the
460 /// specified precision and with the specified rounding mode. Both [`Float`]s are taken by
461 /// value. An [`Ordering`] is also returned, indicating whether the rounded AGM is less than,
462 /// equal to, or greater than the exact AGM. Although `NaN`s are not comparable to any
463 /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
464 ///
465 /// See [`RoundingMode`] for a description of the possible rounding modes.
466 ///
467 /// $$
468 /// f(x,y,p,m) = \text{AGM}(x,y)+\varepsilon
469 /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta}
470 /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon.
471 /// $$
472 /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
473 /// to be 0.
474 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon|
475 /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$.
476 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
477 /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$.
478 ///
479 /// If the output has a precision, it is `prec`.
480 ///
481 /// Special cases:
482 /// - $f(\text{NaN},x,p,m)=f(x,\text{NaN},p,m)=f(-\infty,x,p,m)=f(x,-\infty,p,m)=\text{NaN}$
483 /// - $f(\infty,x,p,m)=f(x,\infty,p,m)=\text{NaN}$ if $x\neq\infty$
484 /// - $f(\infty,\infty,p,m)=\infty$
485 /// - $f(\pm0.0,x,p,m)=f(x,\pm0.0,p,m)=0.0$
486 /// - $f(x,y,p,m)=\text{NaN}$ if $x<0$ or $y<0$
487 ///
488 /// Neither overflow nor underflow is possible.
489 ///
490 /// If you know you'll be using `Nearest`, consider using [`Float::agm_prec`] instead. If you
491 /// know that your target precision is the maximum of the precisions of the two inputs, consider
492 /// using [`Float::agm_round`] instead. If both of these things are true, consider using
493 /// [`Float::agm`] instead.
494 ///
495 /// # Worst-case complexity
496 /// $T(n, m) = O(n (\log n)^2 \log\log n + m)$
497 ///
498 /// $M(n, m) = O(n \log n + m)$
499 ///
500 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
501 /// `max(self.significant_bits(), other.significant_bits())`.
502 ///
503 /// # Panics
504 /// Panics if `rm` is `Exact` but the two [`Float`] arguments are positive and distinct (and the
505 /// exact result is therefore irrational).
506 ///
507 /// # Examples
508 /// ```
509 /// use malachite_base::rounding_modes::RoundingMode::*;
510 /// use malachite_float::Float;
511 /// use std::cmp::Ordering::*;
512 ///
513 /// let (agm, o) = Float::from(24).agm_prec_round(Float::from(6), 5, Floor);
514 /// assert_eq!(agm.to_string(), "13.0");
515 /// assert_eq!(o, Less);
516 ///
517 /// let (agm, o) = Float::from(24).agm_prec_round(Float::from(6), 5, Ceiling);
518 /// assert_eq!(agm.to_string(), "13.5");
519 /// assert_eq!(o, Greater);
520 ///
521 /// let (agm, o) = Float::from(24).agm_prec_round(Float::from(6), 5, Nearest);
522 /// assert_eq!(agm.to_string(), "13.5");
523 /// assert_eq!(o, Greater);
524 ///
525 /// let (agm, o) = Float::from(24).agm_prec_round(Float::from(6), 20, Floor);
526 /// assert_eq!(agm.to_string(), "13.458160");
527 /// assert_eq!(o, Less);
528 ///
529 /// let (agm, o) = Float::from(24).agm_prec_round(Float::from(6), 20, Ceiling);
530 /// assert_eq!(agm.to_string(), "13.458176");
531 /// assert_eq!(o, Greater);
532 ///
533 /// let (agm, o) = Float::from(24).agm_prec_round(Float::from(6), 20, Nearest);
534 /// assert_eq!(agm.to_string(), "13.458176");
535 /// assert_eq!(o, Greater);
536 /// ```
537 #[inline]
538 pub fn agm_prec_round(self, other: Self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
539 assert_ne!(prec, 0);
540 match (&self, &other) {
541 (float_nan!(), _) | (_, float_nan!()) => (float_nan!(), Equal),
542 (float_infinity!(), x) | (x, float_infinity!()) if *x > 0.0 => {
543 (float_infinity!(), Equal)
544 }
545 (float_either_infinity!(), _) | (_, float_either_infinity!()) => (float_nan!(), Equal),
546 (float_either_zero!(), _) | (_, float_either_zero!()) => (float_zero!(), Equal),
547 _ => agm_prec_round_normal(self, other, prec, rm),
548 }
549 }
550
551 /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, rounding the result to the
552 /// specified precision and with the specified rounding mode. The first [`Float`] is taken by
553 /// value and the second by reference. An [`Ordering`] is also returned, indicating whether the
554 /// rounded AGM is less than, equal to, or greater than the exact AGM. Although `NaN`s are not
555 /// comparable to any [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
556 ///
557 /// See [`RoundingMode`] for a description of the possible rounding modes.
558 ///
559 /// $$
560 /// f(x,y,p,m) = \text{AGM}(x,y)+\varepsilon
561 /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta}
562 /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon.
563 /// $$
564 /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
565 /// to be 0.
566 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon|
567 /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$.
568 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
569 /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$.
570 ///
571 /// If the output has a precision, it is `prec`.
572 ///
573 /// Special cases:
574 /// - $f(\text{NaN},x,p,m)=f(x,\text{NaN},p,m)=f(-\infty,x,p,m)=f(x,-\infty,p,m)=\text{NaN}$
575 /// - $f(\infty,x,p,m)=f(x,\infty,p,m)=\text{NaN}$ if $x\neq\infty$
576 /// - $f(\infty,\infty,p,m)=\infty$
577 /// - $f(\pm0.0,x,p,m)=f(x,\pm0.0,p,m)=0.0$
578 /// - $f(x,y,p,m)=\text{NaN}$ if $x<0$ or $y<0$
579 ///
580 /// Neither overflow nor underflow is possible.
581 ///
582 /// If you know you'll be using `Nearest`, consider using [`Float::agm_prec_val_ref`] instead.
583 /// If you know that your target precision is the maximum of the precisions of the two inputs,
584 /// consider using [`Float::agm_round_val_ref`] instead. If both of these things are true,
585 /// consider using [`Float::agm`] instead.
586 ///
587 /// # Worst-case complexity
588 /// $T(n, m) = O(n (\log n)^2 \log\log n + m)$
589 ///
590 /// $M(n, m) = O(n \log n + m)$
591 ///
592 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
593 /// `max(self.significant_bits(), other.significant_bits())`.
594 ///
595 /// # Panics
596 /// Panics if `rm` is `Exact` but the two [`Float`] arguments are positive and distinct (and the
597 /// exact result is therefore irrational).
598 ///
599 /// # Examples
600 /// ```
601 /// use malachite_base::rounding_modes::RoundingMode::*;
602 /// use malachite_float::Float;
603 /// use std::cmp::Ordering::*;
604 ///
605 /// let (agm, o) = Float::from(24).agm_prec_round_val_ref(&Float::from(6), 5, Floor);
606 /// assert_eq!(agm.to_string(), "13.0");
607 /// assert_eq!(o, Less);
608 ///
609 /// let (agm, o) = Float::from(24).agm_prec_round_val_ref(&Float::from(6), 5, Ceiling);
610 /// assert_eq!(agm.to_string(), "13.5");
611 /// assert_eq!(o, Greater);
612 ///
613 /// let (agm, o) = Float::from(24).agm_prec_round_val_ref(&Float::from(6), 5, Nearest);
614 /// assert_eq!(agm.to_string(), "13.5");
615 /// assert_eq!(o, Greater);
616 ///
617 /// let (agm, o) = Float::from(24).agm_prec_round_val_ref(&Float::from(6), 20, Floor);
618 /// assert_eq!(agm.to_string(), "13.458160");
619 /// assert_eq!(o, Less);
620 ///
621 /// let (agm, o) = Float::from(24).agm_prec_round_val_ref(&Float::from(6), 20, Ceiling);
622 /// assert_eq!(agm.to_string(), "13.458176");
623 /// assert_eq!(o, Greater);
624 ///
625 /// let (agm, o) = Float::from(24).agm_prec_round_val_ref(&Float::from(6), 20, Nearest);
626 /// assert_eq!(agm.to_string(), "13.458176");
627 /// assert_eq!(o, Greater);
628 /// ```
629 #[inline]
630 pub fn agm_prec_round_val_ref(
631 mut self,
632 other: &Self,
633 prec: u64,
634 rm: RoundingMode,
635 ) -> (Self, Ordering) {
636 let o = self.agm_prec_round_assign_ref(other, prec, rm);
637 (self, o)
638 }
639
640 /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, rounding the result to the
641 /// specified precision and with the specified rounding mode. The first [`Float`] is taken by
642 /// reference and the second by value. An [`Ordering`] is also returned, indicating whether the
643 /// rounded AGM is less than, equal to, or greater than the exact AGM. Although `NaN`s are not
644 /// comparable to any [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
645 ///
646 /// See [`RoundingMode`] for a description of the possible rounding modes.
647 ///
648 /// $$
649 /// f(x,y,p,m) = \text{AGM}(x,y)+\varepsilon
650 /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta}
651 /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon.
652 /// $$
653 /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
654 /// to be 0.
655 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon|
656 /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$.
657 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
658 /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$.
659 ///
660 /// If the output has a precision, it is `prec`.
661 ///
662 /// Special cases:
663 /// - $f(\text{NaN},x,p,m)=f(x,\text{NaN},p,m)=f(-\infty,x,p,m)=f(x,-\infty,p,m)=\text{NaN}$
664 /// - $f(\infty,x,p,m)=f(x,\infty,p,m)=\text{NaN}$ if $x\neq\infty$
665 /// - $f(\infty,\infty,p,m)=\infty$
666 /// - $f(\pm0.0,x,p,m)=f(x,\pm0.0,p,m)=0.0$
667 /// - $f(x,y,p,m)=\text{NaN}$ if $x<0$ or $y<0$
668 ///
669 /// Neither overflow nor underflow is possible.
670 ///
671 /// If you know you'll be using `Nearest`, consider using [`Float::agm_prec_ref_val`] instead.
672 /// If you know that your target precision is the maximum of the precisions of the two inputs,
673 /// consider using [`Float::agm_round_ref_val`] instead. If both of these things are true,
674 /// consider using [`Float::agm`] instead.
675 ///
676 /// # Worst-case complexity
677 /// $T(n, m) = O(n (\log n)^2 \log\log n + m)$
678 ///
679 /// $M(n, m) = O(n \log n + m)$
680 ///
681 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
682 /// `max(self.significant_bits(), other.significant_bits())`.
683 ///
684 /// # Panics
685 /// Panics if `rm` is `Exact` but the two [`Float`] arguments are positive and distinct (and the
686 /// exact result is therefore irrational).
687 ///
688 /// # Examples
689 /// ```
690 /// use malachite_base::rounding_modes::RoundingMode::*;
691 /// use malachite_float::Float;
692 /// use std::cmp::Ordering::*;
693 ///
694 /// let (agm, o) = Float::from(24).agm_prec_round_val_ref(&Float::from(6), 5, Floor);
695 /// assert_eq!(agm.to_string(), "13.0");
696 /// assert_eq!(o, Less);
697 ///
698 /// let (agm, o) = Float::from(24).agm_prec_round_ref_val(Float::from(6), 5, Ceiling);
699 /// assert_eq!(agm.to_string(), "13.5");
700 /// assert_eq!(o, Greater);
701 ///
702 /// let (agm, o) = Float::from(24).agm_prec_round_ref_val(Float::from(6), 5, Nearest);
703 /// assert_eq!(agm.to_string(), "13.5");
704 /// assert_eq!(o, Greater);
705 ///
706 /// let (agm, o) = Float::from(24).agm_prec_round_ref_val(Float::from(6), 20, Floor);
707 /// assert_eq!(agm.to_string(), "13.458160");
708 /// assert_eq!(o, Less);
709 ///
710 /// let (agm, o) = Float::from(24).agm_prec_round_ref_val(Float::from(6), 20, Ceiling);
711 /// assert_eq!(agm.to_string(), "13.458176");
712 /// assert_eq!(o, Greater);
713 ///
714 /// let (agm, o) = Float::from(24).agm_prec_round_ref_val(Float::from(6), 20, Nearest);
715 /// assert_eq!(agm.to_string(), "13.458176");
716 /// assert_eq!(o, Greater);
717 /// ```
718 #[inline]
719 pub fn agm_prec_round_ref_val(
720 &self,
721 mut other: Self,
722 prec: u64,
723 rm: RoundingMode,
724 ) -> (Self, Ordering) {
725 let o = other.agm_prec_round_assign_ref(self, prec, rm);
726 (other, o)
727 }
728
729 /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, rounding the result to the
730 /// specified precision and with the specified rounding mode. Both [`Float`]s are taken by
731 /// reference. An [`Ordering`] is also returned, indicating whether the rounded AGM is less
732 /// than, equal to, or greater than the exact AGM. Although `NaN`s are not comparable to any
733 /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
734 ///
735 /// See [`RoundingMode`] for a description of the possible rounding modes.
736 ///
737 /// $$
738 /// f(x,y,p,m) = \text{AGM}(x,y)+\varepsilon
739 /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta}
740 /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon.
741 /// $$
742 /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
743 /// to be 0.
744 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon|
745 /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$.
746 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
747 /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$.
748 ///
749 /// If the output has a precision, it is `prec`.
750 ///
751 /// Special cases:
752 /// - $f(\text{NaN},x,p,m)=f(x,\text{NaN},p,m)=f(-\infty,x,p,m)=f(x,-\infty,p,m)=\text{NaN}$
753 /// - $f(\infty,x,p,m)=f(x,\infty,p,m)=\text{NaN}$ if $x\neq\infty$
754 /// - $f(\infty,\infty,p,m)=\infty$
755 /// - $f(\pm0.0,x,p,m)=f(x,\pm0.0,p,m)=0.0$
756 /// - $f(x,y,p,m)=\text{NaN}$ if $x<0$ or $y<0$
757 ///
758 /// Neither overflow nor underflow is possible.
759 ///
760 /// If you know you'll be using `Nearest`, consider using [`Float::agm_prec_ref_ref`] instead.
761 /// If you know that your target precision is the maximum of the precisions of the two inputs,
762 /// consider using [`Float::agm_round_ref_ref`] instead. If both of these things are true,
763 /// consider using [`Float::agm`] instead.
764 ///
765 /// # Worst-case complexity
766 /// $T(n, m) = O(n (\log n)^2 \log\log n + m)$
767 ///
768 /// $M(n, m) = O(n \log n + m)$
769 ///
770 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
771 /// `max(self.significant_bits(), other.significant_bits())`.
772 ///
773 /// # Panics
774 /// Panics if `rm` is `Exact` but the two [`Float`] arguments are positive and distinct (and the
775 /// exact result is therefore irrational).
776 ///
777 /// # Examples
778 /// ```
779 /// use malachite_base::rounding_modes::RoundingMode::*;
780 /// use malachite_float::Float;
781 /// use std::cmp::Ordering::*;
782 ///
783 /// let (agm, o) = Float::from(24).agm_prec_round_ref_ref(&Float::from(6), 5, Floor);
784 /// assert_eq!(agm.to_string(), "13.0");
785 /// assert_eq!(o, Less);
786 ///
787 /// let (agm, o) = Float::from(24).agm_prec_round_ref_ref(&Float::from(6), 5, Ceiling);
788 /// assert_eq!(agm.to_string(), "13.5");
789 /// assert_eq!(o, Greater);
790 ///
791 /// let (agm, o) = Float::from(24).agm_prec_round_ref_ref(&Float::from(6), 5, Nearest);
792 /// assert_eq!(agm.to_string(), "13.5");
793 /// assert_eq!(o, Greater);
794 ///
795 /// let (agm, o) = Float::from(24).agm_prec_round_ref_ref(&Float::from(6), 20, Floor);
796 /// assert_eq!(agm.to_string(), "13.458160");
797 /// assert_eq!(o, Less);
798 ///
799 /// let (agm, o) = Float::from(24).agm_prec_round_ref_ref(&Float::from(6), 20, Ceiling);
800 /// assert_eq!(agm.to_string(), "13.458176");
801 /// assert_eq!(o, Greater);
802 ///
803 /// let (agm, o) = Float::from(24).agm_prec_round_ref_ref(&Float::from(6), 20, Nearest);
804 /// assert_eq!(agm.to_string(), "13.458176");
805 /// assert_eq!(o, Greater);
806 /// ```
807 ///
808 /// This is mpfr_agm from agm.c, MPFR 4.3.0.
809 #[inline]
810 pub fn agm_prec_round_ref_ref(
811 &self,
812 other: &Self,
813 prec: u64,
814 rm: RoundingMode,
815 ) -> (Self, Ordering) {
816 assert_ne!(prec, 0);
817 match (self, other) {
818 (float_nan!(), _) | (_, float_nan!()) => (float_nan!(), Equal),
819 (float_infinity!(), x) | (x, float_infinity!()) if *x > 0.0 => {
820 (float_infinity!(), Equal)
821 }
822 (float_either_infinity!(), _) | (_, float_either_infinity!()) => (float_nan!(), Equal),
823 (float_either_zero!(), _) | (_, float_either_zero!()) => (float_zero!(), Equal),
824 _ => agm_prec_round_ref_ref_normal(self, other, prec, rm),
825 }
826 }
827
828 /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, rounding the result to the
829 /// nearest value of the specified precision. Both [`Float`]s are taken by value. An
830 /// [`Ordering`] is also returned, indicating whether the rounded AGM is less than, equal to, or
831 /// greater than the exact AGM. Although `NaN`s are not comparable to any [`Float`], whenever
832 /// this function returns a `NaN` it also returns `Equal`.
833 ///
834 /// If the agm is equidistant from two [`Float`]s with the specified precision, the [`Float`]
835 /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of
836 /// the `Nearest` rounding mode.
837 ///
838 /// $$
839 /// f(x,y,p) = \text{AGM}(x,y)+\varepsilon
840 /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta}
841 /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon.
842 /// $$
843 /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
844 /// to be 0.
845 /// - If $\text{AGM}(x,y)$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2
846 /// \text{AGM}(x,y)\rfloor-p}$.
847 ///
848 /// If the output has a precision, it is `prec`.
849 ///
850 /// Special cases:
851 /// - $f(\text{NaN},x,p)=f(x,\text{NaN},p)=f(-\infty,x,p)=f(x,-\infty,p)=\text{NaN}$
852 /// - $f(\infty,x,p)=f(x,\infty,p)=\text{NaN}$ if $x\neq\infty$
853 /// - $f(\infty,\infty,p)=\infty$
854 /// - $f(\pm0.0,x,p)=f(x,\pm0.0,p)=0.0$
855 /// - $f(x,y,p)=\text{NaN}$ if $x<0$ or $y<0$
856 ///
857 /// Neither overflow nor underflow is possible.
858 ///
859 /// If you want to use a rounding mode other than `Nearest`, consider using
860 /// [`Float::agm_prec_round`] instead. If you know that your target precision is the maximum of
861 /// the precisions of the two inputs, consider using [`Float::agm`] instead.
862 ///
863 /// # Worst-case complexity
864 /// $T(n, m) = O(n (\log n)^2 \log\log n + m)$
865 ///
866 /// $M(n, m) = O(n \log n + m)$
867 ///
868 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
869 /// `max(self.significant_bits(), other.significant_bits())`.
870 ///
871 /// # Examples
872 /// ```
873 /// use malachite_float::Float;
874 /// use std::cmp::Ordering::*;
875 ///
876 /// let (agm, o) = Float::from(24).agm_prec(Float::from(6), 5);
877 /// assert_eq!(agm.to_string(), "13.5");
878 /// assert_eq!(o, Greater);
879 ///
880 /// let (agm, o) = Float::from(24).agm_prec(Float::from(6), 20);
881 /// assert_eq!(agm.to_string(), "13.458176");
882 /// assert_eq!(o, Greater);
883 /// ```
884 #[inline]
885 pub fn agm_prec(self, other: Self, prec: u64) -> (Self, Ordering) {
886 self.agm_prec_round(other, prec, Nearest)
887 }
888
889 /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, rounding the result to the
890 /// nearest value of the specified precision. The first [`Float`] is taken by value and the
891 /// second by reference. An [`Ordering`] is also returned, indicating whether the rounded AGM is
892 /// less than, equal to, or greater than the exact AGM. Although `NaN`s are not comparable to
893 /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
894 ///
895 /// If the agm is equidistant from two [`Float`]s with the specified precision, the [`Float`]
896 /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of
897 /// the `Nearest` rounding mode.
898 ///
899 /// $$
900 /// f(x,y,p) = \text{AGM}(x,y)+\varepsilon
901 /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta}
902 /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon.
903 /// $$
904 /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
905 /// to be 0.
906 /// - If $\text{AGM}(x,y)$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2
907 /// \text{AGM}(x,y)\rfloor-p}$.
908 ///
909 /// If the output has a precision, it is `prec`.
910 ///
911 /// Special cases:
912 /// - $f(\text{NaN},x,p)=f(x,\text{NaN},p)=f(-\infty,x,p)=f(x,-\infty,p)=\text{NaN}$
913 /// - $f(\infty,x,p)=f(x,\infty,p)=\text{NaN}$ if $x\neq\infty$
914 /// - $f(\infty,\infty,p)=\infty$
915 /// - $f(\pm0.0,x,p)=f(x,\pm0.0,p)=0.0$
916 /// - $f(x,y,p)=\text{NaN}$ if $x<0$ or $y<0$
917 ///
918 /// Neither overflow nor underflow is possible.
919 ///
920 /// If you want to use a rounding mode other than `Nearest`, consider using
921 /// [`Float::agm_prec_round_val_ref`] instead. If you know that your target precision is the
922 /// maximum of the precisions of the two inputs, consider using [`Float::agm`] instead.
923 ///
924 /// # Worst-case complexity
925 /// $T(n, m) = O(n (\log n)^2 \log\log n + m)$
926 ///
927 /// $M(n, m) = O(n \log n + m)$
928 ///
929 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
930 /// `max(self.significant_bits(), other.significant_bits())`.
931 ///
932 /// # Examples
933 /// ```
934 /// use malachite_float::Float;
935 /// use std::cmp::Ordering::*;
936 ///
937 /// let (agm, o) = Float::from(24).agm_prec_val_ref(&Float::from(6), 5);
938 /// assert_eq!(agm.to_string(), "13.5");
939 /// assert_eq!(o, Greater);
940 ///
941 /// let (agm, o) = Float::from(24).agm_prec_val_ref(&Float::from(6), 20);
942 /// assert_eq!(agm.to_string(), "13.458176");
943 /// assert_eq!(o, Greater);
944 /// ```
945 #[inline]
946 pub fn agm_prec_val_ref(self, other: &Self, prec: u64) -> (Self, Ordering) {
947 self.agm_prec_round_val_ref(other, prec, Nearest)
948 }
949
950 /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, rounding the result to the
951 /// nearest value of the specified precision. The first [`Float`] is taken by reference and the
952 /// second by value. An [`Ordering`] is also returned, indicating whether the rounded AGM is
953 /// less than, equal to, or greater than the exact AGM. Although `NaN`s are not comparable to
954 /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
955 ///
956 /// If the agm is equidistant from two [`Float`]s with the specified precision, the [`Float`]
957 /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of
958 /// the `Nearest` rounding mode.
959 ///
960 /// $$
961 /// f(x,y,p) = \text{AGM}(x,y)+\varepsilon
962 /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta}
963 /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon.
964 /// $$
965 /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
966 /// to be 0.
967 /// - If $\text{AGM}(x,y)$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2
968 /// \text{AGM}(x,y)\rfloor-p}$.
969 ///
970 /// If the output has a precision, it is `prec`.
971 ///
972 /// Special cases:
973 /// - $f(\text{NaN},x,p)=f(x,\text{NaN},p)=f(-\infty,x,p)=f(x,-\infty,p)=\text{NaN}$
974 /// - $f(\infty,x,p)=f(x,\infty,p)=\text{NaN}$ if $x\neq\infty$
975 /// - $f(\infty,\infty,p)=\infty$
976 /// - $f(\pm0.0,x,p)=f(x,\pm0.0,p)=0.0$
977 /// - $f(x,y,p)=\text{NaN}$ if $x<0$ or $y<0$
978 ///
979 /// Neither overflow nor underflow is possible.
980 ///
981 /// If you want to use a rounding mode other than `Nearest`, consider using
982 /// [`Float::agm_prec_round_ref_val`] instead. If you know that your target precision is the
983 /// maximum of the precisions of the two inputs, consider using [`Float::agm`] instead.
984 ///
985 /// # Worst-case complexity
986 /// $T(n, m) = O(n (\log n)^2 \log\log n + m)$
987 ///
988 /// $M(n, m) = O(n \log n + m)$
989 ///
990 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
991 /// `max(self.significant_bits(), other.significant_bits())`.
992 ///
993 /// # Examples
994 /// ```
995 /// use malachite_float::Float;
996 /// use std::cmp::Ordering::*;
997 ///
998 /// let (agm, o) = (&Float::from(24)).agm_prec_ref_val(Float::from(6), 5);
999 /// assert_eq!(agm.to_string(), "13.5");
1000 /// assert_eq!(o, Greater);
1001 ///
1002 /// let (agm, o) = (&Float::from(24)).agm_prec_ref_val(Float::from(6), 20);
1003 /// assert_eq!(agm.to_string(), "13.458176");
1004 /// assert_eq!(o, Greater);
1005 /// ```
1006 #[inline]
1007 pub fn agm_prec_ref_val(&self, other: Self, prec: u64) -> (Self, Ordering) {
1008 self.agm_prec_round_ref_val(other, prec, Nearest)
1009 }
1010
1011 /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, rounding the result to the
1012 /// nearest value of the specified precision. Both [`Float`]s are taken by reference. An
1013 /// [`Ordering`] is also returned, indicating whether the rounded AGM is less than, equal to, or
1014 /// greater than the exact AGM. Although `NaN`s are not comparable to any [`Float`], whenever
1015 /// this function returns a `NaN` it also returns `Equal`.
1016 ///
1017 /// If the agm is equidistant from two [`Float`]s with the specified precision, the [`Float`]
1018 /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of
1019 /// the `Nearest` rounding mode.
1020 ///
1021 /// $$
1022 /// f(x,y,p) = \text{AGM}(x,y)+\varepsilon
1023 /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta}
1024 /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon.
1025 /// $$
1026 /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
1027 /// to be 0.
1028 /// - If $\text{AGM}(x,y)$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2
1029 /// \text{AGM}(x,y)\rfloor-p}$.
1030 ///
1031 /// If the output has a precision, it is `prec`.
1032 ///
1033 /// Special cases:
1034 /// - $f(\text{NaN},x,p)=f(x,\text{NaN},p)=f(-\infty,x,p)=f(x,-\infty,p)=\text{NaN}$
1035 /// - $f(\infty,x,p)=f(x,\infty,p)=\text{NaN}$ if $x\neq\infty$
1036 /// - $f(\infty,\infty,p)=\infty$
1037 /// - $f(\pm0.0,x,p)=f(x,\pm0.0,p)=0.0$
1038 /// - $f(x,y,p)=\text{NaN}$ if $x<0$ or $y<0$
1039 ///
1040 /// Neither overflow nor underflow is possible.
1041 ///
1042 /// If you want to use a rounding mode other than `Nearest`, consider using
1043 /// [`Float::agm_prec_round_ref_ref`] instead. If you know that your target precision is the
1044 /// maximum of the precisions of the two inputs, consider using [`Float::agm`] instead.
1045 ///
1046 /// # Worst-case complexity
1047 /// $T(n, m) = O(n (\log n)^2 \log\log n + m)$
1048 ///
1049 /// $M(n, m) = O(n \log n + m)$
1050 ///
1051 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
1052 /// `max(self.significant_bits(), other.significant_bits())`.
1053 ///
1054 /// # Examples
1055 /// ```
1056 /// use malachite_float::Float;
1057 /// use std::cmp::Ordering::*;
1058 ///
1059 /// let (agm, o) = (&Float::from(24)).agm_prec_ref_ref(&Float::from(6), 5);
1060 /// assert_eq!(agm.to_string(), "13.5");
1061 /// assert_eq!(o, Greater);
1062 ///
1063 /// let (agm, o) = (&Float::from(24)).agm_prec_ref_ref(&Float::from(6), 20);
1064 /// assert_eq!(agm.to_string(), "13.458176");
1065 /// assert_eq!(o, Greater);
1066 /// ```
1067 #[inline]
1068 pub fn agm_prec_ref_ref(&self, other: &Self, prec: u64) -> (Self, Ordering) {
1069 self.agm_prec_round_ref_ref(other, prec, Nearest)
1070 }
1071
1072 /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, rounding the result with the
1073 /// specified rounding mode. Both [`Float`]s are taken by value. An [`Ordering`] is also
1074 /// returned, indicating whether the rounded AGM is less than, equal to, or greater than the
1075 /// exact AGM. Although `NaN`s are not comparable to any [`Float`], whenever this function
1076 /// returns a `NaN` it also returns `Equal`.
1077 ///
1078 /// The precision of the output is the maximum of the precision of the inputs. See
1079 /// [`RoundingMode`] for a description of the possible rounding modes.
1080 ///
1081 /// $$
1082 /// f(x,y,m) = \text{AGM}(x,y)+\varepsilon
1083 /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta}
1084 /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon.
1085 /// $$
1086 /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
1087 /// to be 0.
1088 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon|
1089 /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$, where $p$ is the maximum precision of the
1090 /// inputs.
1091 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
1092 /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$, where $p$ is the maximum precision of the
1093 /// inputs.
1094 ///
1095 /// If the output has a precision, it is the maximum of the precisions of the inputs.
1096 ///
1097 /// Special cases:
1098 /// - $f(\text{NaN},x,m)=f(x,\text{NaN},m)=f(-\infty,x,m)=f(x,-\infty,m)=\text{NaN}$
1099 /// - $f(\infty,x,m)=f(x,\infty,m)=\text{NaN}$ if $x\neq\infty$
1100 /// - $f(\infty,\infty,m)=\infty$
1101 /// - $f(\pm0.0,x,m)=f(x,\pm0.0,m)=0.0$
1102 /// - $f(x,y,m)=\text{NaN}$ if $x<0$ or $y<0$
1103 ///
1104 /// Neither overflow nor underflow is possible.
1105 ///
1106 /// If you want to specify an output precision, consider using [`Float::agm_prec_round`]
1107 /// instead. If you know you'll be using the `Nearest` rounding mode, consider using
1108 /// [`Float::agm`] instead.
1109 ///
1110 /// # Worst-case complexity
1111 /// $T(n) = O(n (\log n)^2 \log\log n)$
1112 ///
1113 /// $M(n) = O(n \log n)$
1114 ///
1115 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
1116 /// other.significant_bits())`.
1117 ///
1118 /// # Panics
1119 /// Panics if `rm` is `Exact` but the two [`Float`] arguments are positive and distinct (and the
1120 /// exact result is therefore irrational).
1121 ///
1122 /// # Examples
1123 /// ```
1124 /// use malachite_base::rounding_modes::RoundingMode::*;
1125 /// use malachite_float::Float;
1126 /// use std::cmp::Ordering::*;
1127 ///
1128 /// let (agm, o) = Float::from_unsigned_prec(24u8, 100)
1129 /// .0
1130 /// .agm_round(Float::from(6), Floor);
1131 /// assert_eq!(agm.to_string(), "13.458171481725615420766813156964");
1132 /// assert_eq!(o, Less);
1133 ///
1134 /// let (agm, o) = Float::from_unsigned_prec(24u8, 100)
1135 /// .0
1136 /// .agm_round(Float::from(6), Ceiling);
1137 /// assert_eq!(agm.to_string(), "13.458171481725615420766813156976");
1138 /// assert_eq!(o, Greater);
1139 ///
1140 /// let (agm, o) = Float::from_unsigned_prec(24u8, 100)
1141 /// .0
1142 /// .agm_round(Float::from(6), Nearest);
1143 /// assert_eq!(agm.to_string(), "13.458171481725615420766813156976");
1144 /// assert_eq!(o, Greater);
1145 /// ```
1146 #[inline]
1147 pub fn agm_round(self, other: Self, rm: RoundingMode) -> (Self, Ordering) {
1148 let prec = max(self.significant_bits(), other.significant_bits());
1149 self.agm_prec_round(other, prec, rm)
1150 }
1151
1152 /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, rounding the result with the
1153 /// specified rounding mode. The first [`Float`] is taken by value and the second by reference.
1154 /// An [`Ordering`] is also returned, indicating whether the rounded AGM is less than, equal to,
1155 /// or greater than the exact AGM. Although `NaN`s are not comparable to any [`Float`], whenever
1156 /// this function returns a `NaN` it also returns `Equal`.
1157 ///
1158 /// The precision of the output is the maximum of the precision of the inputs. See
1159 /// [`RoundingMode`] for a description of the possible rounding modes.
1160 ///
1161 /// $$
1162 /// f(x,y,m) = \text{AGM}(x,y)+\varepsilon
1163 /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta}
1164 /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon.
1165 /// $$
1166 /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
1167 /// to be 0.
1168 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon|
1169 /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$, where $p$ is the maximum precision of the
1170 /// inputs.
1171 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
1172 /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$, where $p$ is the maximum precision of the
1173 /// inputs.
1174 ///
1175 /// If the output has a precision, it is the maximum of the precisions of the inputs.
1176 ///
1177 /// Special cases:
1178 /// - $f(\text{NaN},x,m)=f(x,\text{NaN},m)=f(-\infty,x,m)=f(x,-\infty,m)=\text{NaN}$
1179 /// - $f(\infty,x,m)=f(x,\infty,m)=\text{NaN}$ if $x\neq\infty$
1180 /// - $f(\infty,\infty,m)=\infty$
1181 /// - $f(\pm0.0,x,m)=f(x,\pm0.0,m)=0.0$
1182 /// - $f(x,y,m)=\text{NaN}$ if $x<0$ or $y<0$
1183 ///
1184 /// Neither overflow nor underflow is possible.
1185 ///
1186 /// If you want to specify an output precision, consider using [`Float::agm_prec_round_val_ref`]
1187 /// instead. If you know you'll be using the `Nearest` rounding mode, consider using
1188 /// [`Float::agm`] instead.
1189 ///
1190 /// # Worst-case complexity
1191 /// $T(n) = O(n (\log n)^2 \log\log n)$
1192 ///
1193 /// $M(n) = O(m)$
1194 ///
1195 /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
1196 /// other.significant_bits())`, and $m$ is `other.significant_bits()`.
1197 ///
1198 /// # Panics
1199 /// Panics if `rm` is `Exact` but the two [`Float`] arguments are positive and distinct (and the
1200 /// exact result is therefore irrational).
1201 ///
1202 /// # Examples
1203 /// ```
1204 /// use malachite_base::rounding_modes::RoundingMode::*;
1205 /// use malachite_float::Float;
1206 /// use std::cmp::Ordering::*;
1207 ///
1208 /// let (agm, o) = Float::from_unsigned_prec(24u8, 100)
1209 /// .0
1210 /// .agm_round_val_ref(&Float::from(6), Floor);
1211 /// assert_eq!(agm.to_string(), "13.458171481725615420766813156964");
1212 /// assert_eq!(o, Less);
1213 ///
1214 /// let (agm, o) = Float::from_unsigned_prec(24u8, 100)
1215 /// .0
1216 /// .agm_round_val_ref(&Float::from(6), Ceiling);
1217 /// assert_eq!(agm.to_string(), "13.458171481725615420766813156976");
1218 /// assert_eq!(o, Greater);
1219 ///
1220 /// let (agm, o) = Float::from_unsigned_prec(24u8, 100)
1221 /// .0
1222 /// .agm_round_val_ref(&Float::from(6), Nearest);
1223 /// assert_eq!(agm.to_string(), "13.458171481725615420766813156976");
1224 /// assert_eq!(o, Greater);
1225 /// ```
1226 #[inline]
1227 pub fn agm_round_val_ref(self, other: &Self, rm: RoundingMode) -> (Self, Ordering) {
1228 let prec = max(self.significant_bits(), other.significant_bits());
1229 self.agm_prec_round_val_ref(other, prec, rm)
1230 }
1231
1232 /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, rounding the result with the
1233 /// specified rounding mode. The first [`Float`] is taken by reference and the second by value.
1234 /// An [`Ordering`] is also returned, indicating whether the rounded AGM is less than, equal to,
1235 /// or greater than the exact AGM. Although `NaN`s are not comparable to any [`Float`], whenever
1236 /// this function returns a `NaN` it also returns `Equal`.
1237 ///
1238 /// The precision of the output is the maximum of the precision of the inputs. See
1239 /// [`RoundingMode`] for a description of the possible rounding modes.
1240 ///
1241 /// $$
1242 /// f(x,y,m) = \text{AGM}(x,y)+\varepsilon
1243 /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta}
1244 /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon.
1245 /// $$
1246 /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
1247 /// to be 0.
1248 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon|
1249 /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$, where $p$ is the maximum precision of the
1250 /// inputs.
1251 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
1252 /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$, where $p$ is the maximum precision of the
1253 /// inputs.
1254 ///
1255 /// If the output has a precision, it is the maximum of the precisions of the inputs.
1256 ///
1257 /// Special cases:
1258 /// - $f(\text{NaN},x,m)=f(x,\text{NaN},m)=f(-\infty,x,m)=f(x,-\infty,m)=\text{NaN}$
1259 /// - $f(\infty,x,m)=f(x,\infty,m)=\text{NaN}$ if $x\neq\infty$
1260 /// - $f(\infty,\infty,m)=\infty$
1261 /// - $f(\pm0.0,x,m)=f(x,\pm0.0,m)=0.0$
1262 /// - $f(x,y,m)=\text{NaN}$ if $x<0$ or $y<0$
1263 ///
1264 /// Neither overflow nor underflow is possible.
1265 ///
1266 /// If you want to specify an output precision, consider using [`Float::agm_prec_round_ref_val`]
1267 /// instead. If you know you'll be using the `Nearest` rounding mode, consider using
1268 /// [`Float::agm`] instead.
1269 ///
1270 /// # Worst-case complexity
1271 /// $T(n) = O(n (\log n)^2 \log\log n)$
1272 ///
1273 /// $M(n) = O(m)$
1274 ///
1275 /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
1276 /// other.significant_bits())`, and $m$ is `self.significant_bits()`.
1277 ///
1278 /// # Panics
1279 /// Panics if `rm` is `Exact` but the two [`Float`] arguments are positive and distinct (and the
1280 /// exact result is therefore irrational).
1281 ///
1282 /// # Examples
1283 /// ```
1284 /// use malachite_base::rounding_modes::RoundingMode::*;
1285 /// use malachite_float::Float;
1286 /// use std::cmp::Ordering::*;
1287 ///
1288 /// let (agm, o) =
1289 /// (&Float::from_unsigned_prec(24u8, 100).0).agm_round_ref_val(Float::from(6), Floor);
1290 /// assert_eq!(agm.to_string(), "13.458171481725615420766813156964");
1291 /// assert_eq!(o, Less);
1292 ///
1293 /// let (agm, o) =
1294 /// (&Float::from_unsigned_prec(24u8, 100).0).agm_round_ref_val(Float::from(6), Ceiling);
1295 /// assert_eq!(agm.to_string(), "13.458171481725615420766813156976");
1296 /// assert_eq!(o, Greater);
1297 ///
1298 /// let (agm, o) =
1299 /// (&Float::from_unsigned_prec(24u8, 100).0).agm_round_ref_val(Float::from(6), Nearest);
1300 /// assert_eq!(agm.to_string(), "13.458171481725615420766813156976");
1301 /// assert_eq!(o, Greater);
1302 /// ```
1303 #[inline]
1304 pub fn agm_round_ref_val(&self, other: Self, rm: RoundingMode) -> (Self, Ordering) {
1305 let prec = max(self.significant_bits(), other.significant_bits());
1306 self.agm_prec_round_ref_val(other, prec, rm)
1307 }
1308
1309 /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, rounding the result with the
1310 /// specified rounding mode. Both [`Float`]s are taken by reference. An [`Ordering`] is also
1311 /// returned, indicating whether the rounded AGM is less than, equal to, or greater than the
1312 /// exact AGM. Although `NaN`s are not comparable to any [`Float`], whenever this function
1313 /// returns a `NaN` it also returns `Equal`.
1314 ///
1315 /// The precision of the output is the maximum of the precision of the inputs. See
1316 /// [`RoundingMode`] for a description of the possible rounding modes.
1317 ///
1318 /// $$
1319 /// f(x,y,m) = \text{AGM}(x,y)+\varepsilon
1320 /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta}
1321 /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon.
1322 /// $$
1323 /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
1324 /// to be 0.
1325 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon|
1326 /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$, where $p$ is the maximum precision of the
1327 /// inputs.
1328 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
1329 /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$, where $p$ is the maximum precision of the
1330 /// inputs.
1331 ///
1332 /// If the output has a precision, it is the maximum of the precisions of the inputs.
1333 ///
1334 /// Special cases:
1335 /// - $f(\text{NaN},x,m)=f(x,\text{NaN},m)=f(-\infty,x,m)=f(x,-\infty,m)=\text{NaN}$
1336 /// - $f(\infty,x,m)=f(x,\infty,m)=\text{NaN}$ if $x\neq\infty$
1337 /// - $f(\infty,\infty,m)=\infty$
1338 /// - $f(\pm0.0,x,m)=f(x,\pm0.0,m)=0.0$
1339 /// - $f(x,y,m)=\text{NaN}$ if $x<0$ or $y<0$
1340 ///
1341 /// Neither overflow nor underflow is possible.
1342 ///
1343 /// If you want to specify an output precision, consider using [`Float::agm_prec_round_ref_ref`]
1344 /// instead. If you know you'll be using the `Nearest` rounding mode, consider using
1345 /// [`Float::agm`] instead.
1346 ///
1347 /// # Worst-case complexity
1348 /// $T(n) = O(n (\log n)^2 \log\log n)$
1349 ///
1350 /// $M(n) = O(n \log n)$
1351 ///
1352 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
1353 /// other.significant_bits())`.
1354 ///
1355 /// # Panics
1356 /// Panics if `rm` is `Exact` but the two [`Float`] arguments are positive and distinct (and the
1357 /// exact result is therefore irrational).
1358 ///
1359 /// # Examples
1360 /// ```
1361 /// use malachite_base::rounding_modes::RoundingMode::*;
1362 /// use malachite_float::Float;
1363 /// use std::cmp::Ordering::*;
1364 ///
1365 /// let (agm, o) = Float::from_unsigned_prec(24u8, 100)
1366 /// .0
1367 /// .agm_round_ref_ref(&Float::from(6), Floor);
1368 /// assert_eq!(agm.to_string(), "13.458171481725615420766813156964");
1369 /// assert_eq!(o, Less);
1370 ///
1371 /// let (agm, o) = Float::from_unsigned_prec(24u8, 100)
1372 /// .0
1373 /// .agm_round_ref_ref(&Float::from(6), Ceiling);
1374 /// assert_eq!(agm.to_string(), "13.458171481725615420766813156976");
1375 /// assert_eq!(o, Greater);
1376 ///
1377 /// let (agm, o) = Float::from_unsigned_prec(24u8, 100)
1378 /// .0
1379 /// .agm_round_ref_ref(&Float::from(6), Nearest);
1380 /// assert_eq!(agm.to_string(), "13.458171481725615420766813156976");
1381 /// assert_eq!(o, Greater);
1382 /// ```
1383 #[inline]
1384 pub fn agm_round_ref_ref(&self, other: &Self, rm: RoundingMode) -> (Self, Ordering) {
1385 let prec = max(self.significant_bits(), other.significant_bits());
1386 self.agm_prec_round_ref_ref(other, prec, rm)
1387 }
1388
1389 /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, mutating the first one in
1390 /// place, and rounding the result to the specified precision and with the specified rounding
1391 /// mode. The [`Float`] on the right-hand side is taken by value. An [`Ordering`] is returned,
1392 /// indicating whether the rounded AGM is less than, equal to, or greater than the exact AGM.
1393 /// Although `NaN`s are not comparable to any [`Float`], whenever this function sets the
1394 /// [`Float`] to `NaN` it also returns `Equal`.
1395 ///
1396 /// See [`RoundingMode`] for a description of the possible rounding modes.
1397 ///
1398 /// $$
1399 /// x \gets \text{AGM}(x,y)+\varepsilon
1400 /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta}
1401 /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon.
1402 /// $$
1403 /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
1404 /// to be 0.
1405 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon|
1406 /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$.
1407 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
1408 /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$.
1409 ///
1410 /// If the output has a precision, it is `prec`.
1411 ///
1412 /// See the [`Float::agm_prec_round`] documentation for information on special cases, overflow,
1413 /// and underflow.
1414 ///
1415 /// If you know you'll be using `Nearest`, consider using [`Float::agm_prec_assign`] instead. If
1416 /// you know that your target precision is the maximum of the precisions of the two inputs,
1417 /// consider using [`Float::agm_round_assign`] instead. If both of these things are true,
1418 /// consider using [`Float::agm_assign`] instead.
1419 ///
1420 /// # Worst-case complexity
1421 /// $T(n, m) = O(n (\log n)^2 \log\log n + m)$
1422 ///
1423 /// $M(n, m) = O(n \log n + m)$
1424 ///
1425 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
1426 /// `max(self.significant_bits(), other.significant_bits())`.
1427 ///
1428 /// # Panics
1429 /// Panics if `rm` is `Exact` but the two [`Float`] arguments are positive and distinct (and the
1430 /// exact result is therefore irrational).
1431 ///
1432 /// # Examples
1433 /// ```
1434 /// use malachite_base::rounding_modes::RoundingMode::*;
1435 /// use malachite_float::Float;
1436 /// use std::cmp::Ordering::*;
1437 ///
1438 /// let mut x = Float::from(24);
1439 /// assert_eq!(x.agm_prec_round_assign(Float::from(6), 5, Floor), Less);
1440 /// assert_eq!(x.to_string(), "13.0");
1441 ///
1442 /// let mut x = Float::from(24);
1443 /// assert_eq!(x.agm_prec_round_assign(Float::from(6), 5, Ceiling), Greater);
1444 /// assert_eq!(x.to_string(), "13.5");
1445 ///
1446 /// let mut x = Float::from(24);
1447 /// assert_eq!(x.agm_prec_round_assign(Float::from(6), 5, Nearest), Greater);
1448 /// assert_eq!(x.to_string(), "13.5");
1449 ///
1450 /// let mut x = Float::from(24);
1451 /// assert_eq!(x.agm_prec_round_assign(Float::from(6), 20, Floor), Less);
1452 /// assert_eq!(x.to_string(), "13.458160");
1453 ///
1454 /// let mut x = Float::from(24);
1455 /// assert_eq!(
1456 /// x.agm_prec_round_assign(Float::from(6), 20, Ceiling),
1457 /// Greater
1458 /// );
1459 /// assert_eq!(x.to_string(), "13.458176");
1460 ///
1461 /// let mut x = Float::from(24);
1462 /// assert_eq!(
1463 /// x.agm_prec_round_assign(Float::from(6), 20, Nearest),
1464 /// Greater
1465 /// );
1466 /// assert_eq!(x.to_string(), "13.458176");
1467 /// ```
1468 #[inline]
1469 pub fn agm_prec_round_assign(&mut self, other: Self, prec: u64, rm: RoundingMode) -> Ordering {
1470 let o;
1471 let mut x = Self::ZERO;
1472 swap(&mut x, self);
1473 (*self, o) = x.agm_prec_round(other, prec, rm);
1474 o
1475 }
1476
1477 /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, mutating the first one in
1478 /// place, and rounding the result to the specified precision and with the specified rounding
1479 /// mode. The [`Float`] on the right-hand side is taken by reference. An [`Ordering`] is
1480 /// returned, indicating whether the rounded AGM is less than, equal to, or greater than the
1481 /// exact AGM. Although `NaN`s are not comparable to any [`Float`], whenever this function sets
1482 /// the [`Float`] to `NaN` it also returns `Equal`.
1483 ///
1484 /// See [`RoundingMode`] for a description of the possible rounding modes.
1485 ///
1486 /// $$
1487 /// x \gets \text{AGM}(x,y)+\varepsilon
1488 /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta}
1489 /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon.
1490 /// $$
1491 /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
1492 /// to be 0.
1493 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon|
1494 /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$.
1495 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
1496 /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$.
1497 ///
1498 /// If the output has a precision, it is `prec`.
1499 ///
1500 /// See the [`Float::agm_prec_round`] documentation for information on special cases, overflow,
1501 /// and underflow.
1502 ///
1503 /// If you know you'll be using `Nearest`, consider using [`Float::agm_prec_assign_ref`]
1504 /// instead. If you know that your target precision is the maximum of the precisions of the two
1505 /// inputs, consider using [`Float::agm_round_assign_ref`] instead. If both of these things are
1506 /// true, consider using [`Float::agm_assign`] instead.
1507 ///
1508 /// # Worst-case complexity
1509 /// $T(n, m) = O(n (\log n)^2 \log\log n + m)$
1510 ///
1511 /// $M(n, m) = O(n \log n + m)$
1512 ///
1513 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
1514 /// `max(self.significant_bits(), other.significant_bits())`.
1515 ///
1516 /// # Panics
1517 /// Panics if `rm` is `Exact` but the two [`Float`] arguments are positive and distinct (and the
1518 /// exact result is therefore irrational).
1519 ///
1520 /// # Examples
1521 /// ```
1522 /// use malachite_base::rounding_modes::RoundingMode::*;
1523 /// use malachite_float::Float;
1524 /// use std::cmp::Ordering::*;
1525 ///
1526 /// let mut x = Float::from(24);
1527 /// assert_eq!(x.agm_prec_round_assign_ref(&Float::from(6), 5, Floor), Less);
1528 /// assert_eq!(x.to_string(), "13.0");
1529 ///
1530 /// let mut x = Float::from(24);
1531 /// assert_eq!(
1532 /// x.agm_prec_round_assign_ref(&Float::from(6), 5, Ceiling),
1533 /// Greater
1534 /// );
1535 /// assert_eq!(x.to_string(), "13.5");
1536 ///
1537 /// let mut x = Float::from(24);
1538 /// assert_eq!(
1539 /// x.agm_prec_round_assign_ref(&Float::from(6), 5, Nearest),
1540 /// Greater
1541 /// );
1542 /// assert_eq!(x.to_string(), "13.5");
1543 ///
1544 /// let mut x = Float::from(24);
1545 /// assert_eq!(
1546 /// x.agm_prec_round_assign_ref(&Float::from(6), 20, Floor),
1547 /// Less
1548 /// );
1549 /// assert_eq!(x.to_string(), "13.458160");
1550 ///
1551 /// let mut x = Float::from(24);
1552 /// assert_eq!(
1553 /// x.agm_prec_round_assign_ref(&Float::from(6), 20, Ceiling),
1554 /// Greater
1555 /// );
1556 /// assert_eq!(x.to_string(), "13.458176");
1557 ///
1558 /// let mut x = Float::from(24);
1559 /// assert_eq!(
1560 /// x.agm_prec_round_assign_ref(&Float::from(6), 20, Nearest),
1561 /// Greater
1562 /// );
1563 /// assert_eq!(x.to_string(), "13.458176");
1564 /// ```
1565 #[inline]
1566 pub fn agm_prec_round_assign_ref(
1567 &mut self,
1568 other: &Self,
1569 prec: u64,
1570 rm: RoundingMode,
1571 ) -> Ordering {
1572 let o;
1573 (*self, o) = self.agm_prec_round_ref_ref(other, prec, rm);
1574 o
1575 }
1576
1577 /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, mutating the first one in
1578 /// place, and rounding the result to the nearest value of the specified precision. The
1579 /// [`Float`] on the right-hand side is taken by value. An [`Ordering`] is returned, indicating
1580 /// whether the rounded AGM is less than, equal to, or greater than the exact AGM. Although
1581 /// `NaN`s are not comparable to any [`Float`], whenever this function sets the [`Float`] to
1582 /// `NaN` it also returns `Equal`.
1583 ///
1584 /// If the agm is equidistant from two [`Float`]s with the specified precision, the [`Float`]
1585 /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of
1586 /// the `Nearest` rounding mode.
1587 ///
1588 /// $$
1589 /// x \gets \text{AGM}(x,y)+\varepsilon
1590 /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta}
1591 /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon.
1592 /// $$
1593 /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
1594 /// to be 0.
1595 /// - If $\text{AGM}(x,y)$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2
1596 /// \text{AGM}(x,y)\rfloor-p}$.
1597 ///
1598 /// If the output has a precision, it is `prec`.
1599 ///
1600 /// See the [`Float::agm_prec`] documentation for information on special cases, overflow, and
1601 /// underflow.
1602 ///
1603 /// If you want to use a rounding mode other than `Nearest`, consider using
1604 /// [`Float::agm_prec_round_assign`] instead. If you know that your target precision is the
1605 /// maximum of the precisions of the two inputs, consider using [`Float::agm_assign`] instead.
1606 ///
1607 /// # Worst-case complexity
1608 /// $T(n, m) = O(n (\log n)^2 \log\log n + m)$
1609 ///
1610 /// $M(n, m) = O(n \log n + m)$
1611 ///
1612 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
1613 /// `max(self.significant_bits(), other.significant_bits())`.
1614 ///
1615 /// # Examples
1616 /// ```
1617 /// use malachite_float::Float;
1618 /// use std::cmp::Ordering::*;
1619 ///
1620 /// let mut x = Float::from(24);
1621 /// assert_eq!(x.agm_prec_assign(Float::from(6), 5), Greater);
1622 /// assert_eq!(x.to_string(), "13.5");
1623 ///
1624 /// let mut x = Float::from(24);
1625 /// assert_eq!(x.agm_prec_assign(Float::from(6), 20), Greater);
1626 /// assert_eq!(x.to_string(), "13.458176");
1627 /// ```
1628 #[inline]
1629 pub fn agm_prec_assign(&mut self, other: Self, prec: u64) -> Ordering {
1630 self.agm_prec_round_assign(other, prec, Nearest)
1631 }
1632
1633 /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, mutating the first one in
1634 /// place, and rounding the result to the nearest value of the specified precision. The
1635 /// [`Float`] on the right-hand side is taken by reference. An [`Ordering`] is returned,
1636 /// indicating whether the rounded AGM is less than, equal to, or greater than the exact AGM.
1637 /// Although `NaN`s are not comparable to any [`Float`], whenever this function sets the
1638 /// [`Float`] to `NaN` it also returns `Equal`.
1639 ///
1640 /// If the agm is equidistant from two [`Float`]s with the specified precision, the [`Float`]
1641 /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of
1642 /// the `Nearest` rounding mode.
1643 ///
1644 /// $$
1645 /// x \gets \text{AGM}(x,y)+\varepsilon
1646 /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta}
1647 /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon.
1648 /// $$
1649 /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
1650 /// to be 0.
1651 /// - If $\text{AGM}(x,y)$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2
1652 /// \text{AGM}(x,y)\rfloor-p}$.
1653 ///
1654 /// If the output has a precision, it is `prec`.
1655 ///
1656 /// See the [`Float::agm_prec`] documentation for information on special cases, overflow, and
1657 /// underflow.
1658 ///
1659 /// If you want to use a rounding mode other than `Nearest`, consider using
1660 /// [`Float::agm_prec_round_assign_ref`] instead. If you know that your target precision is the
1661 /// maximum of the precisions of the two inputs, consider using [`Float::agm_assign`] instead.
1662 ///
1663 /// # Worst-case complexity
1664 /// $T(n, m) = O(n (\log n)^2 \log\log n + m)$
1665 ///
1666 /// $M(n, m) = O(n \log n + m)$
1667 ///
1668 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
1669 /// `max(self.significant_bits(), other.significant_bits())`.
1670 ///
1671 /// # Examples
1672 /// ```
1673 /// use malachite_float::Float;
1674 /// use std::cmp::Ordering::*;
1675 ///
1676 /// let mut x = Float::from(24);
1677 /// assert_eq!(x.agm_prec_assign_ref(&Float::from(6), 5), Greater);
1678 /// assert_eq!(x.to_string(), "13.5");
1679 ///
1680 /// let mut x = Float::from(24);
1681 /// assert_eq!(x.agm_prec_assign_ref(&Float::from(6), 20), Greater);
1682 /// assert_eq!(x.to_string(), "13.458176");
1683 /// ```
1684 #[inline]
1685 pub fn agm_prec_assign_ref(&mut self, other: &Self, prec: u64) -> Ordering {
1686 self.agm_prec_round_assign_ref(other, prec, Nearest)
1687 }
1688
1689 /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, mutating the first one in
1690 /// place, and rounding the result with the specified rounding mode. The [`Float`] on the
1691 /// right-hand side is taken by value. An [`Ordering`] is returned, indicating whether the
1692 /// rounded AGM is less than, equal to, or greater than the exact AGM. Although `NaN`s are not
1693 /// comparable to any [`Float`], whenever this function sets the [`Float`] to `NaN` it also
1694 /// returns `Equal`.
1695 ///
1696 /// The precision of the output is the maximum of the precision of the inputs. See
1697 /// [`RoundingMode`] for a description of the possible rounding modes.
1698 ///
1699 /// $$
1700 /// x \gets \text{AGM}(x,y)+\varepsilon
1701 /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta}
1702 /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon.
1703 /// $$
1704 /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
1705 /// to be 0.
1706 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon|
1707 /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$, where $p$ is the maximum precision of the
1708 /// inputs.
1709 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
1710 /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$, where $p$ is the maximum precision of the
1711 /// inputs.
1712 ///
1713 /// If the output has a precision, it is the maximum of the precisions of the inputs.
1714 ///
1715 /// See the [`Float::agm_round`] documentation for information on special cases, overflow, and
1716 /// underflow.
1717 ///
1718 /// If you want to specify an output precision, consider using [`Float::agm_prec_round_assign`]
1719 /// instead. If you know you'll be using the `Nearest` rounding mode, consider using
1720 /// [`Float::agm_assign`] instead.
1721 ///
1722 /// # Worst-case complexity
1723 /// $T(n) = O(n (\log n)^2 \log\log n)$
1724 ///
1725 /// $M(n) = O(n \log n)$
1726 ///
1727 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
1728 /// other.significant_bits())`.
1729 ///
1730 /// # Panics
1731 /// Panics if `rm` is `Exact` but the two [`Float`] arguments are positive and distinct (and the
1732 /// exact result is therefore irrational).
1733 ///
1734 /// # Examples
1735 /// ```
1736 /// use malachite_base::rounding_modes::RoundingMode::*;
1737 /// use malachite_float::Float;
1738 /// use std::cmp::Ordering::*;
1739 ///
1740 /// let mut x = Float::from_unsigned_prec(24u8, 100).0;
1741 /// assert_eq!(x.agm_round_assign(Float::from(6), Floor), Less);
1742 /// assert_eq!(x.to_string(), "13.458171481725615420766813156964");
1743 ///
1744 /// let mut x = Float::from_unsigned_prec(24u8, 100).0;
1745 /// assert_eq!(x.agm_round_assign(Float::from(6), Ceiling), Greater);
1746 /// assert_eq!(x.to_string(), "13.458171481725615420766813156976");
1747 ///
1748 /// let mut x = Float::from_unsigned_prec(24u8, 100).0;
1749 /// assert_eq!(x.agm_round_assign(Float::from(6), Nearest), Greater);
1750 /// assert_eq!(x.to_string(), "13.458171481725615420766813156976");
1751 /// ```
1752 #[inline]
1753 pub fn agm_round_assign(&mut self, other: Self, rm: RoundingMode) -> Ordering {
1754 let prec = max(self.significant_bits(), other.significant_bits());
1755 self.agm_prec_round_assign(other, prec, rm)
1756 }
1757
1758 /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, mutating the first one in
1759 /// place, and rounding the result with the specified rounding mode. The [`Float`] on the
1760 /// right-hand side is taken by reference. An [`Ordering`] is returned, indicating whether the
1761 /// rounded AGM is less than, equal to, or greater than the exact AGM. Although `NaN`s are not
1762 /// comparable to any [`Float`], whenever this function sets the [`Float`] to `NaN` it also
1763 /// returns `Equal`.
1764 ///
1765 /// The precision of the output is the maximum of the precision of the inputs. See
1766 /// [`RoundingMode`] for a description of the possible rounding modes.
1767 ///
1768 /// $$
1769 /// x \gets \text{AGM}(x,y)+\varepsilon
1770 /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta}
1771 /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon.
1772 /// $$
1773 /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
1774 /// to be 0.
1775 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon|
1776 /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$, where $p$ is the maximum precision of the
1777 /// inputs.
1778 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
1779 /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$, where $p$ is the maximum precision of the
1780 /// inputs.
1781 ///
1782 /// If the output has a precision, it is the maximum of the precisions of the inputs.
1783 ///
1784 /// See the [`Float::agm_round`] documentation for information on special cases, overflow, and
1785 /// underflow.
1786 ///
1787 /// If you want to specify an output precision, consider using
1788 /// [`Float::agm_prec_round_assign_ref`] instead. If you know you'll be using the `Nearest`
1789 /// rounding mode, consider using [`Float::agm_assign`] instead.
1790 ///
1791 /// # Worst-case complexity
1792 /// $T(n) = O(n (\log n)^2 \log\log n)$
1793 ///
1794 /// $M(n) = O(m)$
1795 ///
1796 /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
1797 /// other.significant_bits())`, and $m$ is `other.significant_bits()`.
1798 ///
1799 /// # Panics
1800 /// Panics if `rm` is `Exact` but the two [`Float`] arguments are positive and distinct (and the
1801 /// exact result is therefore irrational).
1802 ///
1803 /// # Examples
1804 /// ```
1805 /// use malachite_base::rounding_modes::RoundingMode::*;
1806 /// use malachite_float::Float;
1807 /// use std::cmp::Ordering::*;
1808 ///
1809 /// let mut x = Float::from_unsigned_prec(24u8, 100).0;
1810 /// assert_eq!(x.agm_round_assign_ref(&Float::from(6), Floor), Less);
1811 /// assert_eq!(x.to_string(), "13.458171481725615420766813156964");
1812 ///
1813 /// let mut x = Float::from_unsigned_prec(24u8, 100).0;
1814 /// assert_eq!(x.agm_round_assign_ref(&Float::from(6), Ceiling), Greater);
1815 /// assert_eq!(x.to_string(), "13.458171481725615420766813156976");
1816 ///
1817 /// let mut x = Float::from_unsigned_prec(24u8, 100).0;
1818 /// assert_eq!(x.agm_round_assign_ref(&Float::from(6), Nearest), Greater);
1819 /// assert_eq!(x.to_string(), "13.458171481725615420766813156976");
1820 /// ```
1821 #[inline]
1822 pub fn agm_round_assign_ref(&mut self, other: &Self, rm: RoundingMode) -> Ordering {
1823 let prec = max(self.significant_bits(), other.significant_bits());
1824 self.agm_prec_round_assign_ref(other, prec, rm)
1825 }
1826
1827 /// Computes the arithmetic-geometric mean (AGM) of two [`Rational`]s, rounding the result to
1828 /// the specified precision and with the specified rounding mode, and returning the result as a
1829 /// [`Float`]. Both [`Rational`]s are taken by value. An [`Ordering`] is also returned,
1830 /// indicating whether the rounded AGM is less than, equal to, or greater than the exact AGM.
1831 /// Although `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN`
1832 /// it also returns `Equal`.
1833 ///
1834 /// See [`RoundingMode`] for a description of the possible rounding modes.
1835 ///
1836 /// $$
1837 /// f(x,y,p,m) = \text{AGM}(x,y)+\varepsilon
1838 /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta}
1839 /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon.
1840 /// $$
1841 /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
1842 /// to be 0.
1843 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon|
1844 /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$.
1845 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
1846 /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$.
1847 ///
1848 /// If the output has a precision, it is `prec`.
1849 ///
1850 /// Special cases:
1851 /// - $f(0,x,p,m)=f(x,0,p,m)=0.0$
1852 /// - $f(x,y,p,m)=\text{NaN}$ if $x<0$ or $y<0$
1853 ///
1854 /// Overflow and underflow:
1855 /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is
1856 /// returned instead.
1857 /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$
1858 /// is returned instead, where `p` is the precision of the input.
1859 /// - If $0<f(x,y,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
1860 /// - If $0<f(x,t,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
1861 /// instead.
1862 /// - If $0<f(x,y,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
1863 /// - If $2^{-2^{30}-1}<f(x,y,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
1864 /// instead.
1865 ///
1866 /// Since the result is never negative, negative overflow and underflow cannot occur.
1867 ///
1868 /// If you know you'll be using `Nearest`, consider using [`Float::agm_rational_prec`] instead.
1869 ///
1870 /// # Worst-case complexity
1871 /// $T(n, m) = O(n (\log n)^2 \log\log n + m)$
1872 ///
1873 /// $M(n, m) = O(n \log n + m)$
1874 ///
1875 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
1876 /// `max(x.significant_bits(), y.significant_bits())`.
1877 ///
1878 /// # Panics
1879 /// Panics if `rm` is `Exact` but the two [`Rational`] arguments are positive and distinct (and
1880 /// the exact result is therefore irrational).
1881 ///
1882 /// # Examples
1883 /// ```
1884 /// use malachite_base::rounding_modes::RoundingMode::*;
1885 /// use malachite_float::Float;
1886 /// use malachite_q::Rational;
1887 /// use std::cmp::Ordering::*;
1888 ///
1889 /// let (agm, o) = Float::agm_rational_prec_round(
1890 /// Rational::from_unsigneds(2u8, 3),
1891 /// Rational::from_unsigneds(1u8, 5),
1892 /// 20,
1893 /// Floor,
1894 /// );
1895 /// assert_eq!(agm.to_string(), "0.39851093");
1896 /// assert_eq!(o, Less);
1897 ///
1898 /// let (agm, o) = Float::agm_rational_prec_round(
1899 /// Rational::from_unsigneds(2u8, 3),
1900 /// Rational::from_unsigneds(1u8, 5),
1901 /// 20,
1902 /// Ceiling,
1903 /// );
1904 /// assert_eq!(agm.to_string(), "0.39851141");
1905 /// assert_eq!(o, Greater);
1906 ///
1907 /// let (agm, o) = Float::agm_rational_prec_round(
1908 /// Rational::from_unsigneds(2u8, 3),
1909 /// Rational::from_unsigneds(1u8, 5),
1910 /// 20,
1911 /// Nearest,
1912 /// );
1913 /// assert_eq!(agm.to_string(), "0.39851141");
1914 /// assert_eq!(o, Greater);
1915 /// ```
1916 #[allow(clippy::needless_pass_by_value)]
1917 #[inline]
1918 pub fn agm_rational_prec_round(
1919 x: Rational,
1920 y: Rational,
1921 prec: u64,
1922 rm: RoundingMode,
1923 ) -> (Self, Ordering) {
1924 Self::agm_rational_prec_round_val_ref(x, &y, prec, rm)
1925 }
1926
1927 /// Computes the arithmetic-geometric mean (AGM) of two [`Rational`]s, rounding the result to
1928 /// the specified precision and with the specified rounding mode, and returning the result as a
1929 /// [`Float`]. The first [`Rational`]s is taken by value and the second by reference. An
1930 /// [`Ordering`] is also returned, indicating whether the rounded AGM is less than, equal to, or
1931 /// greater than the exact AGM. Although `NaN`s are not comparable to any [`Float`], whenever
1932 /// this function returns a `NaN` it also returns `Equal`.
1933 ///
1934 /// See [`RoundingMode`] for a description of the possible rounding modes.
1935 ///
1936 /// $$
1937 /// f(x,y,p,m) = \text{AGM}(x,y)+\varepsilon
1938 /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta}
1939 /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon.
1940 /// $$
1941 /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
1942 /// to be 0.
1943 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon|
1944 /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$.
1945 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
1946 /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$.
1947 ///
1948 /// If the output has a precision, it is `prec`.
1949 ///
1950 /// Special cases:
1951 /// - $f(0,x,p,m)=f(x,0,p,m)=0.0$
1952 /// - $f(x,y,p,m)=\text{NaN}$ if $x<0$ or $y<0$
1953 ///
1954 /// Overflow and underflow:
1955 /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is
1956 /// returned instead.
1957 /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$
1958 /// is returned instead, where `p` is the precision of the input.
1959 /// - If $0<f(x,y,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
1960 /// - If $0<f(x,t,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
1961 /// instead.
1962 /// - If $0<f(x,y,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
1963 /// - If $2^{-2^{30}-1}<f(x,y,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
1964 /// instead.
1965 ///
1966 /// Since the result is never negative, negative overflow and underflow cannot occur.
1967 ///
1968 /// If you know you'll be using `Nearest`, consider using [`Float::agm_rational_prec_val_ref`]
1969 /// instead.
1970 ///
1971 /// # Worst-case complexity
1972 /// $T(n, m) = O(n (\log n)^2 \log\log n + m)$
1973 ///
1974 /// $M(n, m) = O(n \log n + m)$
1975 ///
1976 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
1977 /// `max(x.significant_bits(), y.significant_bits())`.
1978 ///
1979 /// # Panics
1980 /// Panics if `rm` is `Exact` but the two [`Rational`] arguments are positive and distinct (and
1981 /// the exact result is therefore irrational).
1982 ///
1983 /// # Examples
1984 /// ```
1985 /// use malachite_base::rounding_modes::RoundingMode::*;
1986 /// use malachite_float::Float;
1987 /// use malachite_q::Rational;
1988 /// use std::cmp::Ordering::*;
1989 ///
1990 /// let (agm, o) = Float::agm_rational_prec_round_val_ref(
1991 /// Rational::from_unsigneds(2u8, 3),
1992 /// &Rational::from_unsigneds(1u8, 5),
1993 /// 20,
1994 /// Floor,
1995 /// );
1996 /// assert_eq!(agm.to_string(), "0.39851093");
1997 /// assert_eq!(o, Less);
1998 ///
1999 /// let (agm, o) = Float::agm_rational_prec_round_val_ref(
2000 /// Rational::from_unsigneds(2u8, 3),
2001 /// &Rational::from_unsigneds(1u8, 5),
2002 /// 20,
2003 /// Ceiling,
2004 /// );
2005 /// assert_eq!(agm.to_string(), "0.39851141");
2006 /// assert_eq!(o, Greater);
2007 ///
2008 /// let (agm, o) = Float::agm_rational_prec_round_val_ref(
2009 /// Rational::from_unsigneds(2u8, 3),
2010 /// &Rational::from_unsigneds(1u8, 5),
2011 /// 20,
2012 /// Nearest,
2013 /// );
2014 /// assert_eq!(agm.to_string(), "0.39851141");
2015 /// assert_eq!(o, Greater);
2016 /// ```
2017 pub fn agm_rational_prec_round_val_ref(
2018 x: Rational,
2019 y: &Rational,
2020 prec: u64,
2021 rm: RoundingMode,
2022 ) -> (Self, Ordering) {
2023 assert_ne!(prec, 0);
2024 match (x.sign(), y.sign()) {
2025 (Equal, _) | (_, Equal) => return (float_zero!(), Equal),
2026 (Less, _) | (_, Less) => return (float_nan!(), Equal),
2027 _ => {}
2028 }
2029 if x == *y {
2030 return Self::from_rational_prec_round(x, prec, rm);
2031 }
2032 assert_ne!(rm, Exact, "Inexact AGM");
2033 let x_exp = i32::saturating_from(x.floor_log_base_2_abs()).saturating_add(1);
2034 let y_exp = i32::saturating_from(y.floor_log_base_2_abs()).saturating_add(1);
2035 let x_overflow = x_exp > Self::MAX_EXPONENT;
2036 let y_overflow = y_exp > Self::MAX_EXPONENT;
2037 let x_underflow = x_exp < Self::MIN_EXPONENT;
2038 let y_underflow = y_exp < Self::MIN_EXPONENT;
2039 match (x_overflow, y_overflow, x_underflow, y_underflow) {
2040 (true, true, _, _) => Self::from_rational_prec_round(x, prec, rm),
2041 (_, _, true, true)
2042 if rm != Nearest
2043 || x_exp < Self::MIN_EXPONENT_MINUS_1 && y_exp < Self::MIN_EXPONENT_MINUS_1 =>
2044 {
2045 Self::from_rational_prec_round(x, prec, rm)
2046 }
2047 (false, false, false, false)
2048 if x_exp < Self::MAX_EXPONENT && y_exp < Self::MAX_EXPONENT =>
2049 {
2050 agm_rational_helper(&x, y, prec, rm)
2051 }
2052 _ => agm_rational_helper_extended(&x, y, prec, rm),
2053 }
2054 }
2055
2056 /// Computes the arithmetic-geometric mean (AGM) of two [`Rational`]s, rounding the result to
2057 /// the specified precision and with the specified rounding mode, and returning the result as a
2058 /// [`Float`]. The first [`Rational`]s is taken by reference and the second by value. An
2059 /// [`Ordering`] is also returned, indicating whether the rounded AGM is less than, equal to, or
2060 /// greater than the exact AGM. Although `NaN`s are not comparable to any [`Float`], whenever
2061 /// this function returns a `NaN` it also returns `Equal`.
2062 ///
2063 /// See [`RoundingMode`] for a description of the possible rounding modes.
2064 ///
2065 /// $$
2066 /// f(x,y,p,m) = \text{AGM}(x,y)+\varepsilon
2067 /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta}
2068 /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon.
2069 /// $$
2070 /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
2071 /// to be 0.
2072 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon|
2073 /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$.
2074 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
2075 /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$.
2076 ///
2077 /// If the output has a precision, it is `prec`.
2078 ///
2079 /// Special cases:
2080 /// - $f(0,x,p,m)=f(x,0,p,m)=0.0$
2081 /// - $f(x,y,p,m)=\text{NaN}$ if $x<0$ or $y<0$
2082 ///
2083 /// Overflow and underflow:
2084 /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is
2085 /// returned instead.
2086 /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$
2087 /// is returned instead, where `p` is the precision of the input.
2088 /// - If $0<f(x,y,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
2089 /// - If $0<f(x,t,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
2090 /// instead.
2091 /// - If $0<f(x,y,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
2092 /// - If $2^{-2^{30}-1}<f(x,y,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
2093 /// instead.
2094 ///
2095 /// Since the result is never negative, negative overflow and underflow cannot occur.
2096 ///
2097 /// If you know you'll be using `Nearest`, consider using [`Float::agm_rational_prec_ref_val`]
2098 /// instead.
2099 ///
2100 /// # Worst-case complexity
2101 /// $T(n, m) = O(n (\log n)^2 \log\log n + m)$
2102 ///
2103 /// $M(n, m) = O(n \log n + m)$
2104 ///
2105 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
2106 /// `max(x.significant_bits(), y.significant_bits())`.
2107 ///
2108 /// # Panics
2109 /// Panics if `rm` is `Exact` but the two [`Rational`] arguments are positive and distinct (and
2110 /// the exact result is therefore irrational).
2111 ///
2112 /// # Examples
2113 /// ```
2114 /// use malachite_base::rounding_modes::RoundingMode::*;
2115 /// use malachite_float::Float;
2116 /// use malachite_q::Rational;
2117 /// use std::cmp::Ordering::*;
2118 ///
2119 /// let (agm, o) = Float::agm_rational_prec_round_ref_val(
2120 /// &Rational::from_unsigneds(2u8, 3),
2121 /// Rational::from_unsigneds(1u8, 5),
2122 /// 20,
2123 /// Floor,
2124 /// );
2125 /// assert_eq!(agm.to_string(), "0.39851093");
2126 /// assert_eq!(o, Less);
2127 ///
2128 /// let (agm, o) = Float::agm_rational_prec_round_ref_val(
2129 /// &Rational::from_unsigneds(2u8, 3),
2130 /// Rational::from_unsigneds(1u8, 5),
2131 /// 20,
2132 /// Ceiling,
2133 /// );
2134 /// assert_eq!(agm.to_string(), "0.39851141");
2135 /// assert_eq!(o, Greater);
2136 ///
2137 /// let (agm, o) = Float::agm_rational_prec_round_ref_val(
2138 /// &Rational::from_unsigneds(2u8, 3),
2139 /// Rational::from_unsigneds(1u8, 5),
2140 /// 20,
2141 /// Nearest,
2142 /// );
2143 /// assert_eq!(agm.to_string(), "0.39851141");
2144 /// assert_eq!(o, Greater);
2145 /// ```
2146 pub fn agm_rational_prec_round_ref_val(
2147 x: &Rational,
2148 y: Rational,
2149 prec: u64,
2150 rm: RoundingMode,
2151 ) -> (Self, Ordering) {
2152 assert_ne!(prec, 0);
2153 match (x.sign(), y.sign()) {
2154 (Equal, _) | (_, Equal) => return (float_zero!(), Equal),
2155 (Less, _) | (_, Less) => return (float_nan!(), Equal),
2156 _ => {}
2157 }
2158 if *x == y {
2159 return Self::from_rational_prec_round(y, prec, rm);
2160 }
2161 assert_ne!(rm, Exact, "Inexact AGM");
2162 let x_exp = i32::saturating_from(x.floor_log_base_2_abs()).saturating_add(1);
2163 let y_exp = i32::saturating_from(y.floor_log_base_2_abs()).saturating_add(1);
2164 let x_overflow = x_exp > Self::MAX_EXPONENT;
2165 let y_overflow = y_exp > Self::MAX_EXPONENT;
2166 let x_underflow = x_exp < Self::MIN_EXPONENT;
2167 let y_underflow = y_exp < Self::MIN_EXPONENT;
2168 match (x_overflow, y_overflow, x_underflow, y_underflow) {
2169 (true, true, _, _) => Self::from_rational_prec_round(y, prec, rm),
2170 (_, _, true, true)
2171 if rm != Nearest
2172 || x_exp < Self::MIN_EXPONENT_MINUS_1 && y_exp < Self::MIN_EXPONENT_MINUS_1 =>
2173 {
2174 Self::from_rational_prec_round(y, prec, rm)
2175 }
2176 (false, false, false, false)
2177 if x_exp < Self::MAX_EXPONENT && y_exp < Self::MAX_EXPONENT =>
2178 {
2179 agm_rational_helper(x, &y, prec, rm)
2180 }
2181 _ => agm_rational_helper_extended(x, &y, prec, rm),
2182 }
2183 }
2184
2185 /// Computes the arithmetic-geometric mean (AGM) of two [`Rational`]s, rounding the result to
2186 /// the specified precision and with the specified rounding mode, and returning the result as a
2187 /// [`Float`]. Both [`Rational`]s are taken by reference. An [`Ordering`] is also returned,
2188 /// indicating whether the rounded AGM is less than, equal to, or greater than the exact AGM.
2189 /// Although `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN`
2190 /// it also returns `Equal`.
2191 ///
2192 /// See [`RoundingMode`] for a description of the possible rounding modes.
2193 ///
2194 /// $$
2195 /// f(x,y,p,m) = \text{AGM}(x,y)+\varepsilon
2196 /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta}
2197 /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon.
2198 /// $$
2199 /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
2200 /// to be 0.
2201 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon|
2202 /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$.
2203 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
2204 /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$.
2205 ///
2206 /// If the output has a precision, it is `prec`.
2207 ///
2208 /// Special cases:
2209 /// - $f(0,x,p,m)=f(x,0,p,m)=0.0$
2210 /// - $f(x,y,p,m)=\text{NaN}$ if $x<0$ or $y<0$
2211 ///
2212 /// Overflow and underflow:
2213 /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is
2214 /// returned instead.
2215 /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Floor` or `Down`, $(1-(1/2)^p)2^{2^{30}-1}$
2216 /// is returned instead, where `p` is the precision of the input.
2217 /// - If $0<f(x,y,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
2218 /// - If $0<f(x,t,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
2219 /// instead.
2220 /// - If $0<f(x,y,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
2221 /// - If $2^{-2^{30}-1}<f(x,y,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
2222 /// instead.
2223 ///
2224 /// Since the result is never negative, negative overflow and underflow cannot occur.
2225 ///
2226 /// If you know you'll be using `Nearest`, consider using [`Float::agm_rational_prec_ref_ref`]
2227 /// instead.
2228 ///
2229 /// # Worst-case complexity
2230 /// $T(n, m) = O(n (\log n)^2 \log\log n + m)$
2231 ///
2232 /// $M(n, m) = O(n \log n + m)$
2233 ///
2234 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
2235 /// `max(x.significant_bits(), y.significant_bits())`.
2236 ///
2237 /// # Panics
2238 /// Panics if `rm` is `Exact` but the two [`Rational`] arguments are positive and distinct (and
2239 /// the exact result is therefore irrational).
2240 ///
2241 /// # Examples
2242 /// ```
2243 /// use malachite_base::rounding_modes::RoundingMode::*;
2244 /// use malachite_float::Float;
2245 /// use malachite_q::Rational;
2246 /// use std::cmp::Ordering::*;
2247 ///
2248 /// let (agm, o) = Float::agm_rational_prec_round_ref_ref(
2249 /// &Rational::from_unsigneds(2u8, 3),
2250 /// &Rational::from_unsigneds(1u8, 5),
2251 /// 20,
2252 /// Floor,
2253 /// );
2254 /// assert_eq!(agm.to_string(), "0.39851093");
2255 /// assert_eq!(o, Less);
2256 ///
2257 /// let (agm, o) = Float::agm_rational_prec_round_ref_ref(
2258 /// &Rational::from_unsigneds(2u8, 3),
2259 /// &Rational::from_unsigneds(1u8, 5),
2260 /// 20,
2261 /// Ceiling,
2262 /// );
2263 /// assert_eq!(agm.to_string(), "0.39851141");
2264 /// assert_eq!(o, Greater);
2265 ///
2266 /// let (agm, o) = Float::agm_rational_prec_round_ref_ref(
2267 /// &Rational::from_unsigneds(2u8, 3),
2268 /// &Rational::from_unsigneds(1u8, 5),
2269 /// 20,
2270 /// Nearest,
2271 /// );
2272 /// assert_eq!(agm.to_string(), "0.39851141");
2273 /// assert_eq!(o, Greater);
2274 /// ```
2275 pub fn agm_rational_prec_round_ref_ref(
2276 x: &Rational,
2277 y: &Rational,
2278 prec: u64,
2279 rm: RoundingMode,
2280 ) -> (Self, Ordering) {
2281 assert_ne!(prec, 0);
2282 match (x.sign(), y.sign()) {
2283 (Equal, _) | (_, Equal) => return (float_zero!(), Equal),
2284 (Less, _) | (_, Less) => return (float_nan!(), Equal),
2285 _ => {}
2286 }
2287 if x == y {
2288 return Self::from_rational_prec_round_ref(x, prec, rm);
2289 }
2290 assert_ne!(rm, Exact, "Inexact AGM");
2291 let x_exp = i32::saturating_from(x.floor_log_base_2_abs()).saturating_add(1);
2292 let y_exp = i32::saturating_from(y.floor_log_base_2_abs()).saturating_add(1);
2293 let x_overflow = x_exp > Self::MAX_EXPONENT;
2294 let y_overflow = y_exp > Self::MAX_EXPONENT;
2295 let x_underflow = x_exp < Self::MIN_EXPONENT;
2296 let y_underflow = y_exp < Self::MIN_EXPONENT;
2297 match (x_overflow, y_overflow, x_underflow, y_underflow) {
2298 (true, true, _, _) => Self::from_rational_prec_round_ref(x, prec, rm),
2299 (_, _, true, true)
2300 if rm != Nearest
2301 || x_exp < Self::MIN_EXPONENT_MINUS_1 && y_exp < Self::MIN_EXPONENT_MINUS_1 =>
2302 {
2303 Self::from_rational_prec_round_ref(x, prec, rm)
2304 }
2305 (false, false, false, false)
2306 if x_exp < Self::MAX_EXPONENT && y_exp < Self::MAX_EXPONENT =>
2307 {
2308 agm_rational_helper(x, y, prec, rm)
2309 }
2310 _ => agm_rational_helper_extended(x, y, prec, rm),
2311 }
2312 }
2313
2314 /// Computes the arithmetic-geometric mean (AGM) of two [`Rational`]s, rounding the result to
2315 /// the nearest value of the specified precision, and returning the result as a [`Float`]. Both
2316 /// [`Rational`]s are taken by value. An [`Ordering`] is also returned, indicating whether the
2317 /// rounded AGM is less than, equal to, or greater than the exact AGM. Although `NaN`s are not
2318 /// comparable to any [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
2319 ///
2320 /// See [`RoundingMode`] for a description of the possible rounding modes.
2321 ///
2322 /// $$
2323 /// f(x,y,p) = \text{AGM}(x,y)+\varepsilon
2324 /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta}
2325 /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon.
2326 /// $$
2327 /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
2328 /// to be 0.
2329 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon|
2330 /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$.
2331 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
2332 /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$.
2333 ///
2334 /// If the output has a precision, it is `prec`.
2335 ///
2336 /// Special cases:
2337 /// - $f(0,x,p)=f(x,0,p)=0.0$
2338 /// - $f(x,y,p)=\text{NaN}$ if $x<0$ or $y<0$
2339 ///
2340 /// Overflow and underflow:
2341 /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead.
2342 /// - If $0<f(x,y,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
2343 /// - If $2^{-2^{30}-1}<f(x,y,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
2344 ///
2345 /// Since the result is never negative, negative overflow and underflow cannot occur.
2346 ///
2347 /// If you want to use a rounding mode other than `Nearest`, consider using
2348 /// [`Float::agm_rational_prec_round`] instead.
2349 ///
2350 /// # Worst-case complexity
2351 /// $T(n, m) = O(n (\log n)^2 \log\log n + m)$
2352 ///
2353 /// $M(n, m) = O(n \log n + m)$
2354 ///
2355 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
2356 /// `max(x.significant_bits(), y.significant_bits())`.
2357 ///
2358 /// # Panics
2359 /// Panics if `rm` is `Exact` but the two [`Rational`] arguments are positive and distinct (and
2360 /// the exact result is therefore irrational).
2361 ///
2362 /// # Examples
2363 /// ```
2364 /// use malachite_float::Float;
2365 /// use malachite_q::Rational;
2366 /// use std::cmp::Ordering::*;
2367 ///
2368 /// let (agm, o) = Float::agm_rational_prec(
2369 /// Rational::from_unsigneds(2u8, 3),
2370 /// Rational::from_unsigneds(1u8, 5),
2371 /// 20,
2372 /// );
2373 /// assert_eq!(agm.to_string(), "0.39851141");
2374 /// assert_eq!(o, Greater);
2375 /// ```
2376 #[allow(clippy::needless_pass_by_value)]
2377 #[inline]
2378 pub fn agm_rational_prec(x: Rational, y: Rational, prec: u64) -> (Self, Ordering) {
2379 Self::agm_rational_prec_round_val_ref(x, &y, prec, Nearest)
2380 }
2381
2382 /// Computes the arithmetic-geometric mean (AGM) of two [`Rational`]s, rounding the result to
2383 /// the nearest value of the specified precision, and returning the result as a [`Float`]. The
2384 /// first [`Rational`] is taken by value and the second by reference. An [`Ordering`] is also
2385 /// returned, indicating whether the rounded AGM is less than, equal to, or greater than the
2386 /// exact AGM. Although `NaN`s are not comparable to any [`Float`], whenever this function
2387 /// returns a `NaN` it also returns `Equal`.
2388 ///
2389 /// See [`RoundingMode`] for a description of the possible rounding modes.
2390 ///
2391 /// $$
2392 /// f(x,y,p) = \text{AGM}(x,y)+\varepsilon
2393 /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta}
2394 /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon.
2395 /// $$
2396 /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
2397 /// to be 0.
2398 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon|
2399 /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$.
2400 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
2401 /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$.
2402 ///
2403 /// If the output has a precision, it is `prec`.
2404 ///
2405 /// Special cases:
2406 /// - $f(0,x,p)=f(x,0,p)=0.0$
2407 /// - $f(x,y,p)=\text{NaN}$ if $x<0$ or $y<0$
2408 ///
2409 /// Overflow and underflow:
2410 /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead.
2411 /// - If $0<f(x,y,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
2412 /// - If $2^{-2^{30}-1}<f(x,y,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
2413 ///
2414 /// Since the result is never negative, negative overflow and underflow cannot occur.
2415 ///
2416 /// If you want to use a rounding mode other than `Nearest`, consider using
2417 /// [`Float::agm_rational_prec_round_val_ref`] instead.
2418 ///
2419 /// # Worst-case complexity
2420 /// $T(n, m) = O(n (\log n)^2 \log\log n + m)$
2421 ///
2422 /// $M(n, m) = O(n \log n + m)$
2423 ///
2424 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
2425 /// `max(x.significant_bits(), y.significant_bits())`.
2426 ///
2427 /// # Panics
2428 /// Panics if `rm` is `Exact` but the two [`Rational`] arguments are positive and distinct (and
2429 /// the exact result is therefore irrational).
2430 ///
2431 /// # Examples
2432 /// ```
2433 /// use malachite_float::Float;
2434 /// use malachite_q::Rational;
2435 /// use std::cmp::Ordering::*;
2436 ///
2437 /// let (agm, o) = Float::agm_rational_prec_val_ref(
2438 /// Rational::from_unsigneds(2u8, 3),
2439 /// &Rational::from_unsigneds(1u8, 5),
2440 /// 20,
2441 /// );
2442 /// assert_eq!(agm.to_string(), "0.39851141");
2443 /// assert_eq!(o, Greater);
2444 /// ```
2445 #[inline]
2446 pub fn agm_rational_prec_val_ref(x: Rational, y: &Rational, prec: u64) -> (Self, Ordering) {
2447 Self::agm_rational_prec_round_val_ref(x, y, prec, Nearest)
2448 }
2449
2450 /// Computes the arithmetic-geometric mean (AGM) of two [`Rational`]s, rounding the result to
2451 /// the nearest value of the specified precision, and returning the result as a [`Float`]. The
2452 /// first [`Rational`] is taken by reference and the second by value. An [`Ordering`] is also
2453 /// returned, indicating whether the rounded AGM is less than, equal to, or greater than the
2454 /// exact AGM. Although `NaN`s are not comparable to any [`Float`], whenever this function
2455 /// returns a `NaN` it also returns `Equal`.
2456 ///
2457 /// See [`RoundingMode`] for a description of the possible rounding modes.
2458 ///
2459 /// $$
2460 /// f(x,y,p) = \text{AGM}(x,y)+\varepsilon
2461 /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta}
2462 /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon.
2463 /// $$
2464 /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
2465 /// to be 0.
2466 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon|
2467 /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$.
2468 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
2469 /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$.
2470 ///
2471 /// If the output has a precision, it is `prec`.
2472 ///
2473 /// Special cases:
2474 /// - $f(0,x,p)=f(x,0,p)=0.0$
2475 /// - $f(x,y,p)=\text{NaN}$ if $x<0$ or $y<0$
2476 ///
2477 /// Overflow and underflow:
2478 /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead.
2479 /// - If $0<f(x,y,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
2480 /// - If $2^{-2^{30}-1}<f(x,y,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
2481 ///
2482 /// Since the result is never negative, negative overflow and underflow cannot occur.
2483 ///
2484 /// If you want to use a rounding mode other than `Nearest`, consider using
2485 /// [`Float::agm_rational_prec_round_ref_val`] instead.
2486 ///
2487 /// # Worst-case complexity
2488 /// $T(n, m) = O(n (\log n)^2 \log\log n + m)$
2489 ///
2490 /// $M(n, m) = O(n \log n + m)$
2491 ///
2492 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
2493 /// `max(x.significant_bits(), y.significant_bits())`.
2494 ///
2495 /// # Panics
2496 /// Panics if `rm` is `Exact` but the two [`Rational`] arguments are positive and distinct (and
2497 /// the exact result is therefore irrational).
2498 ///
2499 /// # Examples
2500 /// ```
2501 /// use malachite_float::Float;
2502 /// use malachite_q::Rational;
2503 /// use std::cmp::Ordering::*;
2504 ///
2505 /// let (agm, o) = Float::agm_rational_prec_ref_val(
2506 /// &Rational::from_unsigneds(2u8, 3),
2507 /// Rational::from_unsigneds(1u8, 5),
2508 /// 20,
2509 /// );
2510 /// assert_eq!(agm.to_string(), "0.39851141");
2511 /// assert_eq!(o, Greater);
2512 /// ```
2513 #[inline]
2514 pub fn agm_rational_prec_ref_val(x: &Rational, y: Rational, prec: u64) -> (Self, Ordering) {
2515 Self::agm_rational_prec_round_ref_val(x, y, prec, Nearest)
2516 }
2517
2518 /// Computes the arithmetic-geometric mean (AGM) of two [`Rational`]s, rounding the result to
2519 /// the nearest value of the specified precision, and returning the result as a [`Float`]. Both
2520 /// [`Rational`]s are taken by reference. An [`Ordering`] is also returned, indicating whether
2521 /// the rounded AGM is less than, equal to, or greater than the exact AGM. Although `NaN`s are
2522 /// not comparable to any [`Float`], whenever this function returns a `NaN` it also returns
2523 /// `Equal`.
2524 ///
2525 /// See [`RoundingMode`] for a description of the possible rounding modes.
2526 ///
2527 /// $$
2528 /// f(x,y,p) = \text{AGM}(x,y)+\varepsilon
2529 /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta}
2530 /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon.
2531 /// $$
2532 /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
2533 /// to be 0.
2534 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon|
2535 /// < 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p+1}$.
2536 /// - If $\text{AGM}(x,y)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
2537 /// 2^{\lfloor\log_2 \text{AGM}(x,y)\rfloor-p}$.
2538 ///
2539 /// If the output has a precision, it is `prec`.
2540 ///
2541 /// Special cases:
2542 /// - $f(0,x,p)=f(x,0,p)=0.0$
2543 /// - $f(x,y,p)=\text{NaN}$ if $x<0$ or $y<0$
2544 ///
2545 /// Overflow and underflow:
2546 /// - If $f(x,y,p)\geq 2^{2^{30}-1}$, $\infty$ is returned instead.
2547 /// - If $0<f(x,y,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
2548 /// - If $2^{-2^{30}-1}<f(x,y,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
2549 ///
2550 /// Since the result is never negative, negative overflow and underflow cannot occur.
2551 ///
2552 /// If you want to use a rounding mode other than `Nearest`, consider using
2553 /// [`Float::agm_rational_prec_round_ref_ref`] instead.
2554 ///
2555 /// # Worst-case complexity
2556 /// $T(n, m) = O(n (\log n)^2 \log\log n + m)$
2557 ///
2558 /// $M(n, m) = O(n \log n + m)$
2559 ///
2560 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
2561 /// `max(x.significant_bits(), y.significant_bits())`.
2562 ///
2563 /// # Panics
2564 /// Panics if `rm` is `Exact` but the two [`Rational`] arguments are positive and distinct (and
2565 /// the exact result is therefore irrational).
2566 ///
2567 /// # Examples
2568 /// ```
2569 /// use malachite_float::Float;
2570 /// use malachite_q::Rational;
2571 /// use std::cmp::Ordering::*;
2572 ///
2573 /// let (agm, o) = Float::agm_rational_prec_ref_ref(
2574 /// &Rational::from_unsigneds(2u8, 3),
2575 /// &Rational::from_unsigneds(1u8, 5),
2576 /// 20,
2577 /// );
2578 /// assert_eq!(agm.to_string(), "0.39851141");
2579 /// assert_eq!(o, Greater);
2580 /// ```
2581 #[inline]
2582 pub fn agm_rational_prec_ref_ref(x: &Rational, y: &Rational, prec: u64) -> (Self, Ordering) {
2583 Self::agm_rational_prec_round_ref_ref(x, y, prec, Nearest)
2584 }
2585}
2586
2587impl Agm<Self> for Float {
2588 type Output = Self;
2589
2590 /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, taking both by value.
2591 ///
2592 /// If the output has a precision, it is the maximum of the precisions of the inputs. If the agm
2593 /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s
2594 /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
2595 /// rounding mode.
2596 ///
2597 /// $$
2598 /// f(x,y) = \text{AGM}(x,y)+\varepsilon
2599 /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta}
2600 /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon.
2601 /// $$
2602 /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
2603 /// to be 0.
2604 /// - If $\text{AGM}(x,y)$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2
2605 /// \text{AGM}(x,y)\rfloor-p}$, where $p$ is the maximum precision of the inputs.
2606 ///
2607 /// Special cases:
2608 /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(-\infty,x)=f(x,-\infty)=\text{NaN}$
2609 /// - $f(\infty,x)=f(x,\infty)=\text{NaN}$ if $x\neq\infty$
2610 /// - $f(\infty,\infty)=\infty$
2611 /// - $f(\pm0.0,x)=f(x,\pm0.0)=0.0$
2612 /// - $f(x,y)=\text{NaN}$ if $x<0$ or $y<0$
2613 ///
2614 /// Neither overflow nor underflow is possible.
2615 ///
2616 /// If you want to use a rounding mode other than `Nearest`, consider using [`Float::agm_prec`]
2617 /// instead. If you want to specify the output precision, consider using [`Float::agm_round`].
2618 /// If you want both of these things, consider using [`Float::agm_prec_round`].
2619 ///
2620 /// # Worst-case complexity
2621 /// $T(n) = O(n (\log n)^2 \log\log n)$
2622 ///
2623 /// $M(n) = O(n \log n)$
2624 ///
2625 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
2626 /// other.significant_bits())`.
2627 ///
2628 /// # Examples
2629 /// ```
2630 /// use malachite_base::num::arithmetic::traits::Agm;
2631 /// use malachite_float::Float;
2632 ///
2633 /// assert_eq!(
2634 /// Float::from_unsigned_prec(24u8, 100)
2635 /// .0
2636 /// .agm(Float::from(6))
2637 /// .to_string(),
2638 /// "13.458171481725615420766813156976"
2639 /// );
2640 /// ```
2641 #[inline]
2642 fn agm(self, other: Self) -> Self {
2643 let prec = max(self.significant_bits(), other.significant_bits());
2644 self.agm_prec_round(other, prec, Nearest).0
2645 }
2646}
2647
2648impl Agm<&Self> for Float {
2649 type Output = Self;
2650
2651 /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, taking the first by value
2652 /// and the second by reference.
2653 ///
2654 /// If the output has a precision, it is the maximum of the precisions of the inputs. If the agm
2655 /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s
2656 /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
2657 /// rounding mode.
2658 ///
2659 /// $$
2660 /// f(x,y) = \text{AGM}(x,y)+\varepsilon
2661 /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta}
2662 /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon.
2663 /// $$
2664 /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
2665 /// to be 0.
2666 /// - If $\text{AGM}(x,y)$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2
2667 /// \text{AGM}(x,y)\rfloor-p}$, where $p$ is the maximum precision of the inputs.
2668 ///
2669 /// Special cases:
2670 /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(-\infty,x)=f(x,-\infty)=\text{NaN}$
2671 /// - $f(\infty,x)=f(x,\infty)=\text{NaN}$ if $x\neq\infty$
2672 /// - $f(\infty,\infty)=\infty$
2673 /// - $f(\pm0.0,x)=f(x,\pm0.0)=0.0$
2674 /// - $f(x,y)=\text{NaN}$ if $x<0$ or $y<0$
2675 ///
2676 /// Neither overflow nor underflow is possible.
2677 ///
2678 /// If you want to use a rounding mode other than `Nearest`, consider using
2679 /// [`Float::agm_prec_val_ref`] instead. If you want to specify the output precision, consider
2680 /// using [`Float::agm_round_val_ref`]. If you want both of these things, consider using
2681 /// [`Float::agm_prec_round_val_ref`].
2682 ///
2683 /// # Worst-case complexity
2684 /// $T(n) = O(n (\log n)^2 \log\log n)$
2685 ///
2686 /// $M(n) = O(m)$
2687 ///
2688 /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
2689 /// other.significant_bits())`, and $m$ is `other.significant_bits()`.
2690 ///
2691 /// # Examples
2692 /// ```
2693 /// use malachite_base::num::arithmetic::traits::Agm;
2694 /// use malachite_float::Float;
2695 ///
2696 /// assert_eq!(
2697 /// Float::from_unsigned_prec(24u8, 100)
2698 /// .0
2699 /// .agm(&Float::from(6))
2700 /// .to_string(),
2701 /// "13.458171481725615420766813156976"
2702 /// );
2703 /// ```
2704 #[inline]
2705 fn agm(self, other: &Self) -> Self {
2706 let prec = max(self.significant_bits(), other.significant_bits());
2707 self.agm_prec_round_val_ref(other, prec, Nearest).0
2708 }
2709}
2710
2711impl Agm<Float> for &Float {
2712 type Output = Float;
2713
2714 /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, taking the first by
2715 /// reference and the second by value.
2716 ///
2717 /// If the output has a precision, it is the maximum of the precisions of the inputs. If the agm
2718 /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s
2719 /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
2720 /// rounding mode.
2721 ///
2722 /// $$
2723 /// f(x,y) = \text{AGM}(x,y)+\varepsilon
2724 /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta}
2725 /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon.
2726 /// $$
2727 /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
2728 /// to be 0.
2729 /// - If $\text{AGM}(x,y)$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2
2730 /// \text{AGM}(x,y)\rfloor-p}$, where $p$ is the maximum precision of the inputs.
2731 ///
2732 /// Special cases:
2733 /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(-\infty,x)=f(x,-\infty)=\text{NaN}$
2734 /// - $f(\infty,x)=f(x,\infty)=\text{NaN}$ if $x\neq\infty$
2735 /// - $f(\infty,\infty)=\infty$
2736 /// - $f(\pm0.0,x)=f(x,\pm0.0)=0.0$
2737 /// - $f(x,y)=\text{NaN}$ if $x<0$ or $y<0$
2738 ///
2739 /// Neither overflow nor underflow is possible.
2740 ///
2741 /// If you want to use a rounding mode other than `Nearest`, consider using
2742 /// [`Float::agm_prec_ref_val`] instead. If you want to specify the output precision, consider
2743 /// using [`Float::agm_round_ref_val`]. If you want both of these things, consider using
2744 /// [`Float::agm_prec_round_ref_val`].
2745 ///
2746 /// # Worst-case complexity
2747 /// $T(n) = O(n (\log n)^2 \log\log n)$
2748 ///
2749 /// $M(n) = O(m)$
2750 ///
2751 /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
2752 /// other.significant_bits())`, and $m$ is `self.significant_bits()`.
2753 ///
2754 /// # Examples
2755 /// ```
2756 /// use malachite_base::num::arithmetic::traits::Agm;
2757 /// use malachite_float::Float;
2758 ///
2759 /// assert_eq!(
2760 /// (&Float::from_unsigned_prec(24u8, 100).0)
2761 /// .agm(Float::from(6))
2762 /// .to_string(),
2763 /// "13.458171481725615420766813156976"
2764 /// );
2765 /// ```
2766 #[inline]
2767 fn agm(self, other: Float) -> Float {
2768 let prec = max(self.significant_bits(), other.significant_bits());
2769 self.agm_prec_round_ref_val(other, prec, Nearest).0
2770 }
2771}
2772
2773impl Agm<&Float> for &Float {
2774 type Output = Float;
2775
2776 /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, taking both by reference.
2777 ///
2778 /// If the output has a precision, it is the maximum of the precisions of the inputs. If the agm
2779 /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s
2780 /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
2781 /// rounding mode.
2782 ///
2783 /// $$
2784 /// f(x,y) = \text{AGM}(x,y)+\varepsilon
2785 /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta}
2786 /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon.
2787 /// $$
2788 /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
2789 /// to be 0.
2790 /// - If $\text{AGM}(x,y)$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2
2791 /// \text{AGM}(x,y)\rfloor-p}$, where $p$ is the maximum precision of the inputs.
2792 ///
2793 /// Special cases:
2794 /// - $f(\text{NaN},x)=f(x,\text{NaN})=f(-\infty,x)=f(x,-\infty)=\text{NaN}$
2795 /// - $f(\infty,x)=f(x,\infty)=\text{NaN}$ if $x\neq\infty$
2796 /// - $f(\infty,\infty)=\infty$
2797 /// - $f(\pm0.0,x)=f(x,\pm0.0)=0.0$
2798 /// - $f(x,y)=\text{NaN}$ if $x<0$ or $y<0$
2799 ///
2800 /// Neither overflow nor underflow is possible.
2801 ///
2802 /// If you want to use a rounding mode other than `Nearest`, consider using
2803 /// [`Float::agm_prec_ref_ref`] instead. If you want to specify the output precision, consider
2804 /// using [`Float::agm_round_ref_ref`]. If you want both of these things, consider using
2805 /// [`Float::agm_prec_round_ref_ref`].
2806 ///
2807 /// # Worst-case complexity
2808 /// $T(n) = O(n (\log n)^2 \log\log n)$
2809 ///
2810 /// $M(n) = O(n \log n)$
2811 ///
2812 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
2813 /// other.significant_bits())`.
2814 ///
2815 /// # Examples
2816 /// ```
2817 /// use malachite_base::num::arithmetic::traits::Agm;
2818 /// use malachite_float::Float;
2819 ///
2820 /// assert_eq!(
2821 /// (&Float::from_unsigned_prec(24u8, 100).0)
2822 /// .agm(&Float::from(6))
2823 /// .to_string(),
2824 /// "13.458171481725615420766813156976"
2825 /// );
2826 /// ```
2827 #[inline]
2828 fn agm(self, other: &Float) -> Float {
2829 let prec = max(self.significant_bits(), other.significant_bits());
2830 self.agm_prec_round_ref_ref(other, prec, Nearest).0
2831 }
2832}
2833
2834impl AgmAssign<Self> for Float {
2835 /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, mutating the first one in
2836 /// place, and taking the [`Float`] on the right-hand side by value.
2837 ///
2838 /// If the output has a precision, it is the maximum of the precisions of the inputs. If the agm
2839 /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s
2840 /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
2841 /// rounding mode.
2842 ///
2843 /// $$
2844 /// x\gets = \text{AGM}(x,y)+\varepsilon
2845 /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta}
2846 /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon.
2847 /// $$
2848 /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
2849 /// to be 0.
2850 /// - If $\text{AGM}(x,y)$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2
2851 /// \text{AGM}(x,y)\rfloor-p}$, where $p$ is the maximum precision of the inputs.
2852 ///
2853 /// See the [`Float::agm`] documentation for information on special cases, overflow, and
2854 /// underflow.
2855 ///
2856 /// If you want to use a rounding mode other than `Nearest`, consider using
2857 /// [`Float::agm_prec_assign`] instead. If you want to specify the output precision, consider
2858 /// using [`Float::agm_round_assign`]. If you want both of these things, consider using
2859 /// [`Float::agm_prec_round_assign`].
2860 ///
2861 /// # Worst-case complexity
2862 /// $T(n) = O(n (\log n)^2 \log\log n)$
2863 ///
2864 /// $M(n) = O(n \log n)$
2865 ///
2866 /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
2867 /// other.significant_bits())`.
2868 ///
2869 /// # Examples
2870 /// ```
2871 /// use malachite_base::num::arithmetic::traits::AgmAssign;
2872 /// use malachite_float::Float;
2873 ///
2874 /// let mut x = Float::from_unsigned_prec(24u8, 100).0;
2875 /// x.agm_assign(Float::from(6));
2876 /// assert_eq!(x.to_string(), "13.458171481725615420766813156976");
2877 /// ```
2878 #[inline]
2879 fn agm_assign(&mut self, other: Self) {
2880 let prec = max(self.significant_bits(), other.significant_bits());
2881 self.agm_prec_round_assign(other, prec, Nearest);
2882 }
2883}
2884
2885impl AgmAssign<&Self> for Float {
2886 /// Computes the arithmetic-geometric mean (AGM) of two [`Float`]s, mutating the first one in
2887 /// place, and taking the [`Float`] on the right-hand side by reference.
2888 ///
2889 /// If the output has a precision, it is the maximum of the precisions of the inputs. If the agm
2890 /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s
2891 /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
2892 /// rounding mode.
2893 ///
2894 /// $$
2895 /// x\gets = \text{AGM}(x,y)+\varepsilon
2896 /// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta}
2897 /// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon.
2898 /// $$
2899 /// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
2900 /// to be 0.
2901 /// - If $\text{AGM}(x,y)$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2
2902 /// \text{AGM}(x,y)\rfloor-p}$, where $p$ is the maximum precision of the inputs.
2903 ///
2904 /// See the [`Float::agm`] documentation for information on special cases, overflow, and
2905 /// underflow.
2906 ///
2907 /// If you want to use a rounding mode other than `Nearest`, consider using
2908 /// [`Float::agm_prec_assign_ref`] instead. If you want to specify the output precision,
2909 /// consider using [`Float::agm_round_assign_ref`]. If you want both of these things, consider
2910 /// using [`Float::agm_prec_round_assign_ref`].
2911 ///
2912 /// # Worst-case complexity
2913 /// $T(n) = O(n (\log n)^2 \log\log n)$
2914 ///
2915 /// $M(n) = O(m)$
2916 ///
2917 /// where $T$ is time, $M$ is additional memory, $n$ is `max(self.significant_bits(),
2918 /// other.significant_bits())`, and $m$ is `other.significant_bits()`.
2919 ///
2920 /// # Examples
2921 /// ```
2922 /// use malachite_base::num::arithmetic::traits::AgmAssign;
2923 /// use malachite_float::Float;
2924 ///
2925 /// let mut x = Float::from_unsigned_prec(24u8, 100).0;
2926 /// x.agm_assign(&Float::from(6));
2927 /// assert_eq!(x.to_string(), "13.458171481725615420766813156976");
2928 /// ```
2929 #[inline]
2930 fn agm_assign(&mut self, other: &Self) {
2931 let prec = max(self.significant_bits(), other.significant_bits());
2932 self.agm_prec_round_assign_ref(other, prec, Nearest);
2933 }
2934}
2935
2936/// Computes the arithmetic-geometric mean (AGM) of two primitive floats.
2937///
2938/// $$
2939/// f(x,y) = \text{AGM}(x,y)+\varepsilon
2940/// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta}
2941/// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon.
2942/// $$
2943/// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to
2944/// be 0.
2945/// - If $\text{AGM}(x,y)$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2
2946/// \text{AGM}(x,y)\rfloor-p}$, where $p$ is precision of the output (typically 24 if `T` is a
2947/// [`f32`] and 53 if `T` is a [`f64`], but less if the output is subnormal).
2948///
2949/// Special cases:
2950/// - $f(\text{NaN},x)=f(x,\text{NaN})=f(-\infty,x)=f(x,-\infty)=\text{NaN}$
2951/// - $f(\infty,x)=f(x,\infty)=\text{NaN}$ if $x\neq\infty$
2952/// - $f(\infty,\infty)=\infty$
2953/// - $f(\pm0.0,x)=f(x,\pm0.0)=0.0$
2954/// - $f(x,y)=\text{NaN}$ if $x<0$ or $y<0$
2955///
2956/// # Worst-case complexity
2957/// Constant time and additional memory.
2958///
2959/// # Examples
2960/// ```
2961/// use malachite_base::num::float::NiceFloat;
2962/// use malachite_float::float::arithmetic::agm::primitive_float_agm;
2963///
2964/// assert_eq!(
2965/// NiceFloat(primitive_float_agm(24.0, 6.0)),
2966/// NiceFloat(13.458171481725616)
2967/// );
2968/// ```
2969#[allow(clippy::type_repetition_in_bounds)]
2970#[inline]
2971pub fn primitive_float_agm<T: PrimitiveFloat>(x: T, y: T) -> T
2972where
2973 Float: From<T> + PartialOrd<T>,
2974 for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
2975{
2976 emulate_float_float_to_float_fn(Float::agm_prec, x, y)
2977}
2978
2979/// Computes the arithmetic-geometric mean (AGM) of two [`Rational`]s, returning the result as a
2980/// primitive float.
2981///
2982/// $$
2983/// f(x,y) = \text{AGM}(x,y)+\varepsilon
2984/// =\frac{\pi}{2}\left(\int_0^{\frac{\pi}{2}}\frac{\mathrm{d}\theta}
2985/// {\sqrt{x^2\cos^2\theta+y^2\sin^2\theta}}\right)^{-1}+\varepsilon.
2986/// $$
2987/// - If $\text{AGM}(x,y)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to
2988/// be 0.
2989/// - If $\text{AGM}(x,y)$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2
2990/// \text{AGM}(x,y)\rfloor-p}$, where $p$ is precision of the output (typically 24 if `T` is a
2991/// [`f32`] and 53 if `T` is a [`f64`], but less if the output is subnormal).
2992///
2993/// Special cases:
2994/// - $f(0,x)=f(x,0)=0.0$
2995/// - $f(x,y)=\text{NaN}$ if $x<0$ or $y<0$
2996///
2997/// # Worst-case complexity
2998/// $T(m) = O(m)$
2999///
3000/// $M(m) = O(m)$
3001///
3002/// where $T$ is time, $M$ is additional memory, and $m$ is `max(x.significant_bits(),
3003/// y.significant_bits())`.
3004///
3005/// # Examples
3006/// ```
3007/// use malachite_base::num::float::NiceFloat;
3008/// use malachite_float::float::arithmetic::agm::primitive_float_agm_rational;
3009/// use malachite_q::Rational;
3010///
3011/// assert_eq!(
3012/// NiceFloat(primitive_float_agm_rational::<f64>(
3013/// &Rational::from_unsigneds(2u8, 3),
3014/// &Rational::from_unsigneds(1u8, 5)
3015/// )),
3016/// NiceFloat(0.3985113702200345)
3017/// );
3018/// ```
3019#[allow(clippy::type_repetition_in_bounds)]
3020#[inline]
3021pub fn primitive_float_agm_rational<T: PrimitiveFloat>(x: &Rational, y: &Rational) -> T
3022where
3023 Float: PartialOrd<T>,
3024 for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
3025{
3026 emulate_rational_rational_to_float_fn(Float::agm_rational_prec_ref_ref, x, y)
3027}