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