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