Skip to main content

malachite_float/float/arithmetic/
hypot.rs

1// Copyright © 2026 Mikhail Hogrefe
2//
3// Uses code adopted from the GNU MPFR Library.
4//
5//      Copyright 2001-2025 Free Software Foundation, Inc.
6//
7//      Contributed by the Pascaline 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::arithmetic::round_near_x::float_round_near_x;
17use crate::float::{MAX_EXPONENT_I64, MIN_EXPONENT_I64, WIDTH_MINUS_1};
18use crate::{
19    Float, emulate_float_float_to_float_fn, float_either_infinity, float_either_zero,
20    float_infinity, float_nan, significand_bits,
21};
22use core::cmp::Ordering::{self, *};
23use core::cmp::{max, min};
24use core::mem::swap;
25use malachite_base::fail_on_untested_path;
26use malachite_base::num::arithmetic::traits::{Abs, CeilingLogBase2, Hypot, HypotAssign, Square};
27use malachite_base::num::basic::floats::PrimitiveFloat;
28use malachite_base::num::basic::integers::PrimitiveInt;
29use malachite_base::num::basic::traits::Zero as ZeroTrait;
30use malachite_base::num::comparison::traits::PartialOrdAbs;
31use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom};
32use malachite_base::num::logic::traits::SignificantBits;
33use malachite_base::rounding_modes::RoundingMode::{self, *};
34use malachite_nz::natural::Natural;
35use malachite_nz::natural::arithmetic::float::round::float_can_round;
36use malachite_nz::natural::arithmetic::float::sqrt::sqrt_float_significand_ref;
37use malachite_nz::platform::Limb;
38
39// Exact integer-level path. Both inputs are finite and nonzero. The exact sum of squares is formed
40// as x^2 + y^2 = s * 2^(2k) with s a `Natural`, and its square root is taken by the raw
41// significand-level kernel behind `Float::sqrt_prec_round`, which consumes the whole of s (its
42// sticky accounting covers every dropped bit) but only produces `prec` bits. Since the arithmetic
43// is on integers and the kernel is indifferent to where the binade actually lies -- only the
44// exponent's parity matters -- no exponent-range trouble is possible until the result is assembled,
45// where a too-large exponent saturates just as an overflowing `shl` would. This path has no
46// analogue in the C code; it replaces MPFR's FIXME concerning the underflow of the scaled y, and
47// also decides `Exact` directly: the kernel's ternary value is `Equal` if and only if the square
48// root is exactly representable at `prec` bits.
49fn hypot_exact_helper(x: &Float, y: &Float, prec: u64, rm: RoundingMode) -> (Float, Ordering) {
50    let (
51        Float(Finite {
52            exponent: x_exponent,
53            significand: x_significand,
54            ..
55        }),
56        Float(Finite {
57            exponent: y_exponent,
58            significand: y_significand,
59            ..
60        }),
61    ) = (x, y)
62    else {
63        unreachable!()
64    };
65    // lsb-anchored decompositions |x| = mx * 2^lx and |y| = my * 2^ly, with trailing zeros stripped
66    // to keep the squares small
67    let decompose = |significand: &Natural, exponent: i32| {
68        let tz = significand.trailing_zeros().unwrap();
69        (
70            significand >> tz,
71            i64::from(exponent) - i64::exact_from(significand_bits(significand))
72                + i64::exact_from(tz),
73        )
74    };
75    let (mx, lx) = decompose(x_significand, *x_exponent);
76    let (my, ly) = decompose(y_significand, *y_exponent);
77    let a = min(lx, ly);
78    let s = (mx.square() << (u64::exact_from(lx - a) << 1))
79        + (my.square() << (u64::exact_from(ly - a) << 1));
80    // Normalize s into significand form (top bit at a limb boundary; the low padding bits are
81    // zero), representing the value 0.s * 2^e with e = bits(s) + 2k, where k = a. The kernel only
82    // cares about e's parity, so it is passed as just the parity bit, and the discarded even part
83    // is restored afterwards.
84    let s_bits = s.significant_bits();
85    let sn = s << (s_bits.wrapping_neg() & WIDTH_MINUS_1);
86    let e = i64::exact_from(s_bits) + (a << 1);
87    let e_syn = i32::exact_from(e.rem_euclid(2));
88    let delta = (e - i64::from(e_syn)) >> 1;
89    let (root, out_exp, o) = sqrt_float_significand_ref(
90        &sn,
91        e_syn,
92        s_bits,
93        prec,
94        if rm == Exact { Floor } else { rm },
95    );
96    if rm == Exact {
97        assert_eq!(o, Equal, "Inexact Float hypot");
98    }
99    let exp = i64::from(out_exp) + delta;
100    // The true result is in [|x|, sqrt(2) * (|x| + ulp)), so its exponent is E_x or E_x + 1, and
101    // underflow is impossible; overflow is possible only when E_x is at the very top of the range.
102    if exp > MAX_EXPONENT_I64 {
103        assert_ne!(rm, Exact, "Inexact Float hypot");
104        return match rm {
105            Floor | Down => {
106                // Rounding toward zero cannot leave the exponent range: the exact path is only
107                // reached with an exponent gap too large for the second operand to affect the first
108                // operand's binade, so the true result is strictly below 2^Emax whenever its floor
109                // is representable at all. The arm is only defensive.
110                fail_on_untested_path("hypot_exact_helper, overflow with Floor or Down");
111                (Float::max_finite_value_with_prec(prec), Less)
112            }
113            _ => (float_infinity!(), Greater),
114        };
115    }
116    (
117        Float(Finite {
118            sign: true,
119            exponent: i32::exact_from(exp),
120            precision: prec,
121            significand: root,
122        }),
123        o,
124    )
125}
126
127// This is mpfr_hypot from hypot.c, MPFR 4.2.2, with two house deviations, described below. Both
128// inputs are finite and nonzero; the singular cases are handled by the callers.
129fn hypot_prec_round_helper(x: &Float, y: &Float, prec: u64, rm: RoundingMode) -> (Float, Ordering) {
130    // Ensure |x| >= |y|.
131    let (x, y) = if x.lt_abs(y) { (y, x) } else { (x, y) };
132    let ex = i64::from(x.get_exponent().unwrap());
133    let ey = i64::from(y.get_exponent().unwrap());
134    let diff_exp = u64::exact_from(ex - ey);
135    let px = x.significant_bits();
136    let py = y.significant_bits();
137    // Is |x| a suitable approximation to the precision `prec`? When the exponent gap is above this
138    // threshold, hypot(x, y) = |x| + g with 0 < g < 2^(E_x - 2 * diff_exp), and the result is never
139    // exactly representable (see algorithms.tex), so the rounding can be determined from |x| alone,
140    // and `Exact` always panics. The C code hand-rolls the rounding (including the round-up-on-tie
141    // behavior under Nearest and the add-one-ulp adjustments); float_round_near_x is the same
142    // computation.
143    let threshold = (max(px, prec) + u64::from(rm == Nearest)) << 1;
144    if diff_exp > threshold {
145        assert_ne!(rm, Exact, "Inexact Float hypot");
146        // Only take the absolute value if it actually changes anything: `Abs` on a reference copies
147        // the whole significand, which can be huge in exactly this regime.
148        let abs_x_owned;
149        let abs_x = if *x > 0u32 {
150            x
151        } else {
152            abs_x_owned = x.abs();
153            &abs_x_owned
154        };
155        if let Some(r) = float_round_near_x(abs_x, diff_exp << 1, true, prec, rm) {
156            return r;
157        }
158        // Since diff_exp > threshold, the error exponent exceeds both precision bounds that
159        // float_round_near_x checks, so it never declines; the fallthrough is only defensive.
160        fail_on_untested_path("hypot_prec_round_helper, float_round_near_x declined");
161        // Since diff_exp > threshold, the error exponent 2 * diff_exp exceeds both the working
162        // precision bounds float_round_near_x checks, so it always succeeds; but fall through to
163        // the general path defensively.
164    }
165    // General case. The Ziv loop below scales x and y to avoid any overflow and underflow in x^2
166    // (as |x| >= |y|): x = Mx * 2^Ex with 1/2 <= |Mx| < 1, and sh = floor((Emax - 1) / 2) - Ex, so
167    // that (x * 2^sh)^2 = Mx^2 * 2^(2 * floor((Emax - 1) / 2)) has an exponent of at most Emax - 1,
168    // and (x * 2^sh)^2 + (y * 2^sh)^2 one of at most Emax, even after rounding, as the intermediate
169    // operations round toward zero.
170    //
171    // First house deviation: the C code has a FIXME admitting that the scaled y can underflow (the
172    // shortcut above bounds diff_exp by about 2 * max(px, prec), which for huge precisions exceeds
173    // the exponent range). Instead of inheriting that wrong-result corner, such cases go through
174    // the exact integer-level path, which is immune to the exponent range. Second house deviation:
175    // `Exact` also goes through the exact path, which decides exactness directly instead of
176    // looping; the C code does not support an `Exact` mode at all.
177    let sh = const { (MAX_EXPONENT_I64 - 1) >> 1 } - ex;
178    if rm == Exact || ey + sh < MIN_EXPONENT_I64 {
179        return hypot_exact_helper(x, y, prec, rm);
180    }
181    let n = max(px, py);
182    let mut working_prec = prec + prec.ceiling_log_base_2() + 4;
183    let mut increment = Limb::WIDTH;
184    loop {
185        // All intermediate operations round toward zero.
186        let (mut te, o1) = x.shl_prec_round_ref(sh, working_prec, Down);
187        let (ti, o2) = y.shl_prec_round_ref(sh, working_prec, Down);
188        let o3 = te.square_round_assign(Down);
189        // Use fma in order to avoid underflow of ti * ti.
190        let (mut t, o4) = te.add_mul_round_val_ref_ref(&ti, &ti, Down);
191        let o5 = t.sqrt_round_assign(Down);
192        let exact = o1 == Equal && o2 == Equal && o3 == Equal && o4 == Equal && o5 == Equal;
193        if exact {
194            // t is exactly the scaled hypotenuse; the final rounding determines everything.
195            return t.shr_prec_round(sh, prec, rm);
196        }
197        let err = if working_prec < n { 4 } else { 2 };
198        if float_can_round(t.significand_ref().unwrap(), working_prec - err, prec, rm) {
199            let (z, o) = t.shr_prec_round(sh, prec, rm);
200            // mirrors MPFR_ASSERTD (exact == 0 || inexact != 0), which is also debug-only
201            debug_assert_ne!(o, Equal);
202            return (z, o);
203        }
204        working_prec += increment;
205        increment = working_prec >> 1;
206    }
207}
208
209impl Float {
210    /// Computes the hypotenuse of two [`Float`]s, $\sqrt{x^2+y^2}$, rounding the result to the
211    /// specified precision and with the specified rounding mode. Both [`Float`]s are taken by
212    /// value. An [`Ordering`] is also returned, indicating whether the rounded hypotenuse is less
213    /// than, equal to, or greater than the exact hypotenuse. Although `NaN`s are not comparable to
214    /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
215    ///
216    /// See [`RoundingMode`] for a description of the possible rounding modes.
217    ///
218    /// $$
219    /// f(x,y,p,m) = \sqrt{x^2+y^2}+\varepsilon.
220    /// $$
221    /// - If $\sqrt{x^2+y^2}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
222    ///   to be 0.
223    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
224    ///   2^{\lfloor\log_2 \sqrt{x^2+y^2}\rfloor-p+1}$.
225    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
226    ///   2^{\lfloor\log_2 \sqrt{x^2+y^2}\rfloor-p}$.
227    ///
228    /// If the output has a precision, it is `prec`.
229    ///
230    /// Special cases:
231    /// - $f(\pm\infty,x,p,m)=f(x,\pm\infty,p,m)=\infty$, even when the other argument is `NaN`
232    /// - $f(\text{NaN},x,p,m)=f(x,\text{NaN},p,m)=\text{NaN}$ if $x$ is not infinite
233    /// - $f(\pm0.0,\pm0.0,p,m)=0.0$
234    ///
235    /// The result is never negative, and a zero result is always positive.
236    ///
237    /// Overflow:
238    /// - If $f(x,y,p,m)\geq 2^{2^{30}-1}$ and $m$ is `Ceiling`, `Up`, or `Nearest`, $\infty$ is
239    ///   returned instead.
240    /// - 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}$
241    ///   is returned instead, where `p` is the precision of the output.
242    ///
243    /// Underflow is not possible, since the hypotenuse is at least as large as the absolute value
244    /// of each argument.
245    ///
246    /// If you know you'll be using `Nearest`, consider using [`Float::hypot_prec`] instead. If you
247    /// know that your target precision is the maximum of the precisions of the two inputs, consider
248    /// using [`Float::hypot_round`] instead. If both of these things are true, consider using
249    /// [`Float::hypot`] instead.
250    ///
251    /// # Worst-case complexity
252    /// $T(n, m) = O((n + m) \log (n + m) \log\log (n + m))$
253    ///
254    /// $M(n, m) = O(n + m)$
255    ///
256    /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
257    /// `max(self.significant_bits(), other.significant_bits())`.
258    ///
259    /// # Panics
260    /// Panics if `prec` is zero, or if `rm` is `Exact` and the hypotenuse is not exactly
261    /// representable with `prec` bits.
262    ///
263    /// # Examples
264    /// ```
265    /// use malachite_base::num::basic::traits::{One, Two};
266    /// use malachite_base::rounding_modes::RoundingMode::*;
267    /// use malachite_float::Float;
268    /// use std::cmp::Ordering::*;
269    ///
270    /// let (hypot, o) = Float::ONE.hypot_prec_round(Float::TWO, 5, Floor);
271    /// assert_eq!(hypot.to_string(), "2.12");
272    /// assert_eq!(o, Less);
273    ///
274    /// let (hypot, o) = Float::ONE.hypot_prec_round(Float::TWO, 5, Ceiling);
275    /// assert_eq!(hypot.to_string(), "2.25");
276    /// assert_eq!(o, Greater);
277    ///
278    /// let (hypot, o) = Float::ONE.hypot_prec_round(Float::TWO, 5, Nearest);
279    /// assert_eq!(hypot.to_string(), "2.25");
280    /// assert_eq!(o, Greater);
281    ///
282    /// let (hypot, o) = Float::ONE.hypot_prec_round(Float::TWO, 20, Floor);
283    /// assert_eq!(hypot.to_string(), "2.2360649");
284    /// assert_eq!(o, Less);
285    ///
286    /// let (hypot, o) = Float::ONE.hypot_prec_round(Float::TWO, 20, Ceiling);
287    /// assert_eq!(hypot.to_string(), "2.2360687");
288    /// assert_eq!(o, Greater);
289    ///
290    /// let (hypot, o) = Float::ONE.hypot_prec_round(Float::TWO, 20, Nearest);
291    /// assert_eq!(hypot.to_string(), "2.2360687");
292    /// assert_eq!(o, Greater);
293    /// ```
294    pub fn hypot_prec_round(self, other: Self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
295        assert_ne!(prec, 0);
296        match (&self, &other) {
297            // Return +Infinity, even when the other number is NaN.
298            (float_either_infinity!(), _) | (_, float_either_infinity!()) => {
299                (float_infinity!(), Equal)
300            }
301            (float_nan!(), _) | (_, float_nan!()) => (float_nan!(), Equal),
302            (float_either_zero!(), _) => Self::from_float_prec_round(other.abs(), prec, rm),
303            (_, float_either_zero!()) => Self::from_float_prec_round(self.abs(), prec, rm),
304            _ => hypot_prec_round_helper(&self, &other, prec, rm),
305        }
306    }
307
308    /// Computes the hypotenuse of two [`Float`]s, $\sqrt{x^2+y^2}$, rounding the result to the
309    /// specified precision and with the specified rounding mode. The first [`Float`] is taken by
310    /// value and the second by reference. An [`Ordering`] is also returned, indicating whether the
311    /// rounded hypotenuse is less than, equal to, or greater than the exact hypotenuse. Although
312    /// `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN` it also
313    /// returns `Equal`.
314    ///
315    /// See [`RoundingMode`] for a description of the possible rounding modes.
316    ///
317    /// $$
318    /// f(x,y,p,m) = \sqrt{x^2+y^2}+\varepsilon.
319    /// $$
320    /// - If $\sqrt{x^2+y^2}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
321    ///   to be 0.
322    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
323    ///   2^{\lfloor\log_2 \sqrt{x^2+y^2}\rfloor-p+1}$.
324    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
325    ///   2^{\lfloor\log_2 \sqrt{x^2+y^2}\rfloor-p}$.
326    ///
327    /// If the output has a precision, it is `prec`.
328    ///
329    /// See the [`Float::hypot_prec_round`] documentation for information on special cases,
330    /// overflow, and underflow.
331    ///
332    /// If you know you'll be using `Nearest`, consider using [`Float::hypot_prec_val_ref`] instead.
333    /// If you know that your target precision is the maximum of the precisions of the two inputs,
334    /// consider using [`Float::hypot_round_val_ref`] instead. If both of these things are true,
335    /// consider using [`Float::hypot`] instead.
336    ///
337    /// # Worst-case complexity
338    /// $T(n, m) = O((n + m) \log (n + m) \log\log (n + m))$
339    ///
340    /// $M(n, m) = O(n + m)$
341    ///
342    /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
343    /// `max(self.significant_bits(), other.significant_bits())`.
344    ///
345    /// # Panics
346    /// Panics if `prec` is zero, or if `rm` is `Exact` and the hypotenuse is not exactly
347    /// representable with `prec` bits.
348    ///
349    /// # Examples
350    /// ```
351    /// use malachite_base::num::basic::traits::{One, Two};
352    /// use malachite_base::rounding_modes::RoundingMode::*;
353    /// use malachite_float::Float;
354    /// use std::cmp::Ordering::*;
355    ///
356    /// let (hypot, o) = Float::ONE.hypot_prec_round_val_ref(&Float::TWO, 5, Floor);
357    /// assert_eq!(hypot.to_string(), "2.12");
358    /// assert_eq!(o, Less);
359    ///
360    /// let (hypot, o) = Float::ONE.hypot_prec_round_val_ref(&Float::TWO, 5, Ceiling);
361    /// assert_eq!(hypot.to_string(), "2.25");
362    /// assert_eq!(o, Greater);
363    ///
364    /// let (hypot, o) = Float::ONE.hypot_prec_round_val_ref(&Float::TWO, 5, Nearest);
365    /// assert_eq!(hypot.to_string(), "2.25");
366    /// assert_eq!(o, Greater);
367    ///
368    /// let (hypot, o) = Float::ONE.hypot_prec_round_val_ref(&Float::TWO, 20, Floor);
369    /// assert_eq!(hypot.to_string(), "2.2360649");
370    /// assert_eq!(o, Less);
371    ///
372    /// let (hypot, o) = Float::ONE.hypot_prec_round_val_ref(&Float::TWO, 20, Ceiling);
373    /// assert_eq!(hypot.to_string(), "2.2360687");
374    /// assert_eq!(o, Greater);
375    ///
376    /// let (hypot, o) = Float::ONE.hypot_prec_round_val_ref(&Float::TWO, 20, Nearest);
377    /// assert_eq!(hypot.to_string(), "2.2360687");
378    /// assert_eq!(o, Greater);
379    /// ```
380    pub fn hypot_prec_round_val_ref(
381        self,
382        other: &Self,
383        prec: u64,
384        rm: RoundingMode,
385    ) -> (Self, Ordering) {
386        assert_ne!(prec, 0);
387        match (&self, other) {
388            // Return +Infinity, even when the other number is NaN.
389            (float_either_infinity!(), _) | (_, float_either_infinity!()) => {
390                (float_infinity!(), Equal)
391            }
392            (float_nan!(), _) | (_, float_nan!()) => (float_nan!(), Equal),
393            (float_either_zero!(), _) => Self::from_float_prec_round(other.abs(), prec, rm),
394            (_, float_either_zero!()) => Self::from_float_prec_round(self.abs(), prec, rm),
395            _ => hypot_prec_round_helper(&self, other, prec, rm),
396        }
397    }
398
399    /// Computes the hypotenuse of two [`Float`]s, $\sqrt{x^2+y^2}$, rounding the result to the
400    /// specified precision and with the specified rounding mode. The first [`Float`] is taken by
401    /// reference and the second by value. An [`Ordering`] is also returned, indicating whether the
402    /// rounded hypotenuse is less than, equal to, or greater than the exact hypotenuse. Although
403    /// `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN` it also
404    /// returns `Equal`.
405    ///
406    /// See [`RoundingMode`] for a description of the possible rounding modes.
407    ///
408    /// $$
409    /// f(x,y,p,m) = \sqrt{x^2+y^2}+\varepsilon.
410    /// $$
411    /// - If $\sqrt{x^2+y^2}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
412    ///   to be 0.
413    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
414    ///   2^{\lfloor\log_2 \sqrt{x^2+y^2}\rfloor-p+1}$.
415    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
416    ///   2^{\lfloor\log_2 \sqrt{x^2+y^2}\rfloor-p}$.
417    ///
418    /// If the output has a precision, it is `prec`.
419    ///
420    /// See the [`Float::hypot_prec_round`] documentation for information on special cases,
421    /// overflow, and underflow.
422    ///
423    /// If you know you'll be using `Nearest`, consider using [`Float::hypot_prec_ref_val`] instead.
424    /// If you know that your target precision is the maximum of the precisions of the two inputs,
425    /// consider using [`Float::hypot_round_ref_val`] instead. If both of these things are true,
426    /// consider using [`Float::hypot`] instead.
427    ///
428    /// # Worst-case complexity
429    /// $T(n, m) = O((n + m) \log (n + m) \log\log (n + m))$
430    ///
431    /// $M(n, m) = O(n + m)$
432    ///
433    /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
434    /// `max(self.significant_bits(), other.significant_bits())`.
435    ///
436    /// # Panics
437    /// Panics if `prec` is zero, or if `rm` is `Exact` and the hypotenuse is not exactly
438    /// representable with `prec` bits.
439    ///
440    /// # Examples
441    /// ```
442    /// use malachite_base::num::basic::traits::{One, Two};
443    /// use malachite_base::rounding_modes::RoundingMode::*;
444    /// use malachite_float::Float;
445    /// use std::cmp::Ordering::*;
446    ///
447    /// let (hypot, o) = Float::ONE.hypot_prec_round_ref_val(Float::TWO, 5, Floor);
448    /// assert_eq!(hypot.to_string(), "2.12");
449    /// assert_eq!(o, Less);
450    ///
451    /// let (hypot, o) = Float::ONE.hypot_prec_round_ref_val(Float::TWO, 5, Ceiling);
452    /// assert_eq!(hypot.to_string(), "2.25");
453    /// assert_eq!(o, Greater);
454    ///
455    /// let (hypot, o) = Float::ONE.hypot_prec_round_ref_val(Float::TWO, 5, Nearest);
456    /// assert_eq!(hypot.to_string(), "2.25");
457    /// assert_eq!(o, Greater);
458    ///
459    /// let (hypot, o) = Float::ONE.hypot_prec_round_ref_val(Float::TWO, 20, Floor);
460    /// assert_eq!(hypot.to_string(), "2.2360649");
461    /// assert_eq!(o, Less);
462    ///
463    /// let (hypot, o) = Float::ONE.hypot_prec_round_ref_val(Float::TWO, 20, Ceiling);
464    /// assert_eq!(hypot.to_string(), "2.2360687");
465    /// assert_eq!(o, Greater);
466    ///
467    /// let (hypot, o) = Float::ONE.hypot_prec_round_ref_val(Float::TWO, 20, Nearest);
468    /// assert_eq!(hypot.to_string(), "2.2360687");
469    /// assert_eq!(o, Greater);
470    /// ```
471    pub fn hypot_prec_round_ref_val(
472        &self,
473        other: Self,
474        prec: u64,
475        rm: RoundingMode,
476    ) -> (Self, Ordering) {
477        assert_ne!(prec, 0);
478        match (self, &other) {
479            // Return +Infinity, even when the other number is NaN.
480            (float_either_infinity!(), _) | (_, float_either_infinity!()) => {
481                (float_infinity!(), Equal)
482            }
483            (float_nan!(), _) | (_, float_nan!()) => (float_nan!(), Equal),
484            (float_either_zero!(), _) => Self::from_float_prec_round(other.abs(), prec, rm),
485            (_, float_either_zero!()) => Self::from_float_prec_round(self.abs(), prec, rm),
486            _ => hypot_prec_round_helper(self, &other, prec, rm),
487        }
488    }
489
490    /// Computes the hypotenuse of two [`Float`]s, $\sqrt{x^2+y^2}$, rounding the result to the
491    /// specified precision and with the specified rounding mode. Both [`Float`]s are taken by
492    /// reference. An [`Ordering`] is also returned, indicating whether the rounded hypotenuse is
493    /// less than, equal to, or greater than the exact hypotenuse. Although `NaN`s are not
494    /// comparable to any [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
495    ///
496    /// See [`RoundingMode`] for a description of the possible rounding modes.
497    ///
498    /// $$
499    /// f(x,y,p,m) = \sqrt{x^2+y^2}+\varepsilon.
500    /// $$
501    /// - If $\sqrt{x^2+y^2}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
502    ///   to be 0.
503    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
504    ///   2^{\lfloor\log_2 \sqrt{x^2+y^2}\rfloor-p+1}$.
505    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
506    ///   2^{\lfloor\log_2 \sqrt{x^2+y^2}\rfloor-p}$.
507    ///
508    /// If the output has a precision, it is `prec`.
509    ///
510    /// See the [`Float::hypot_prec_round`] documentation for information on special cases,
511    /// overflow, and underflow.
512    ///
513    /// If you know you'll be using `Nearest`, consider using [`Float::hypot_prec_ref_ref`] instead.
514    /// If you know that your target precision is the maximum of the precisions of the two inputs,
515    /// consider using [`Float::hypot_round_ref_ref`] instead. If both of these things are true,
516    /// consider using [`Float::hypot`] instead.
517    ///
518    /// # Worst-case complexity
519    /// $T(n, m) = O((n + m) \log (n + m) \log\log (n + m))$
520    ///
521    /// $M(n, m) = O(n + m)$
522    ///
523    /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
524    /// `max(self.significant_bits(), other.significant_bits())`.
525    ///
526    /// # Panics
527    /// Panics if `prec` is zero, or if `rm` is `Exact` and the hypotenuse is not exactly
528    /// representable with `prec` bits.
529    ///
530    /// # Examples
531    /// ```
532    /// use malachite_base::num::basic::traits::{One, Two};
533    /// use malachite_base::rounding_modes::RoundingMode::*;
534    /// use malachite_float::Float;
535    /// use std::cmp::Ordering::*;
536    ///
537    /// let (hypot, o) = Float::ONE.hypot_prec_round_ref_ref(&Float::TWO, 5, Floor);
538    /// assert_eq!(hypot.to_string(), "2.12");
539    /// assert_eq!(o, Less);
540    ///
541    /// let (hypot, o) = Float::ONE.hypot_prec_round_ref_ref(&Float::TWO, 5, Ceiling);
542    /// assert_eq!(hypot.to_string(), "2.25");
543    /// assert_eq!(o, Greater);
544    ///
545    /// let (hypot, o) = Float::ONE.hypot_prec_round_ref_ref(&Float::TWO, 5, Nearest);
546    /// assert_eq!(hypot.to_string(), "2.25");
547    /// assert_eq!(o, Greater);
548    ///
549    /// let (hypot, o) = Float::ONE.hypot_prec_round_ref_ref(&Float::TWO, 20, Floor);
550    /// assert_eq!(hypot.to_string(), "2.2360649");
551    /// assert_eq!(o, Less);
552    ///
553    /// let (hypot, o) = Float::ONE.hypot_prec_round_ref_ref(&Float::TWO, 20, Ceiling);
554    /// assert_eq!(hypot.to_string(), "2.2360687");
555    /// assert_eq!(o, Greater);
556    ///
557    /// let (hypot, o) = Float::ONE.hypot_prec_round_ref_ref(&Float::TWO, 20, Nearest);
558    /// assert_eq!(hypot.to_string(), "2.2360687");
559    /// assert_eq!(o, Greater);
560    /// ```
561    pub fn hypot_prec_round_ref_ref(
562        &self,
563        other: &Self,
564        prec: u64,
565        rm: RoundingMode,
566    ) -> (Self, Ordering) {
567        assert_ne!(prec, 0);
568        match (self, other) {
569            // Return +Infinity, even when the other number is NaN.
570            (float_either_infinity!(), _) | (_, float_either_infinity!()) => {
571                (float_infinity!(), Equal)
572            }
573            (float_nan!(), _) | (_, float_nan!()) => (float_nan!(), Equal),
574            (float_either_zero!(), _) => Self::from_float_prec_round(other.abs(), prec, rm),
575            (_, float_either_zero!()) => Self::from_float_prec_round(self.abs(), prec, rm),
576            _ => hypot_prec_round_helper(self, other, prec, rm),
577        }
578    }
579
580    /// Computes the hypotenuse of two [`Float`]s, $\sqrt{x^2+y^2}$, rounding the result to the
581    /// nearest value of the specified precision. Both [`Float`]s are taken by value. An
582    /// [`Ordering`] is also returned, indicating whether the rounded hypotenuse is less than, equal
583    /// to, or greater than the exact hypotenuse. Although `NaN`s are not comparable to any
584    /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
585    ///
586    /// If the hypotenuse is equidistant from two [`Float`]s with the specified precision, the
587    /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
588    /// description of the `Nearest` rounding mode.
589    ///
590    /// $$
591    /// f(x,y,p) = \sqrt{x^2+y^2}+\varepsilon.
592    /// $$
593    /// - If $\sqrt{x^2+y^2}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
594    ///   to be 0.
595    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, then $|\varepsilon| \leq 2^{\lfloor\log_2
596    ///   \sqrt{x^2+y^2}\rfloor-p}$.
597    ///
598    /// If the output has a precision, it is `prec`.
599    ///
600    /// See the [`Float::hypot_prec_round`] documentation for information on special cases,
601    /// overflow, and underflow.
602    ///
603    /// If you want to use a rounding mode other than `Nearest`, consider using
604    /// [`Float::hypot_prec_round`] instead. If you know that your target precision is the maximum
605    /// of the precisions of the two inputs, consider using [`Float::hypot`] instead.
606    ///
607    /// # Worst-case complexity
608    /// $T(n, m) = O((n + m) \log (n + m) \log\log (n + m))$
609    ///
610    /// $M(n, m) = O(n + m)$
611    ///
612    /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
613    /// `max(self.significant_bits(), other.significant_bits())`.
614    ///
615    /// # Panics
616    /// Panics if `prec` is zero.
617    ///
618    /// # Examples
619    /// ```
620    /// use core::f64::consts::{E, PI};
621    /// use malachite_float::Float;
622    /// use std::cmp::Ordering::*;
623    ///
624    /// let (hypot, o) = Float::from(PI).hypot_prec(Float::from(E), 5);
625    /// assert_eq!(hypot.to_string(), "4.25");
626    /// assert_eq!(o, Greater);
627    ///
628    /// let (hypot, o) = Float::from(PI).hypot_prec(Float::from(E), 20);
629    /// assert_eq!(hypot.to_string(), "4.1543579");
630    /// assert_eq!(o, Greater);
631    /// ```
632    #[inline]
633    pub fn hypot_prec(self, other: Self, prec: u64) -> (Self, Ordering) {
634        self.hypot_prec_round(other, prec, Nearest)
635    }
636
637    /// Computes the hypotenuse of two [`Float`]s, $\sqrt{x^2+y^2}$, rounding the result to the
638    /// nearest value of the specified precision. The first [`Float`] is taken by value and the
639    /// second by reference. An [`Ordering`] is also returned, indicating whether the rounded
640    /// hypotenuse is less than, equal to, or greater than the exact hypotenuse. Although `NaN`s are
641    /// not comparable to any [`Float`], whenever this function returns a `NaN` it also returns
642    /// `Equal`.
643    ///
644    /// If the hypotenuse is equidistant from two [`Float`]s with the specified precision, the
645    /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
646    /// description of the `Nearest` rounding mode.
647    ///
648    /// $$
649    /// f(x,y,p) = \sqrt{x^2+y^2}+\varepsilon.
650    /// $$
651    /// - If $\sqrt{x^2+y^2}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
652    ///   to be 0.
653    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, then $|\varepsilon| \leq 2^{\lfloor\log_2
654    ///   \sqrt{x^2+y^2}\rfloor-p}$.
655    ///
656    /// If the output has a precision, it is `prec`.
657    ///
658    /// See the [`Float::hypot_prec_round`] documentation for information on special cases,
659    /// overflow, and underflow.
660    ///
661    /// If you want to use a rounding mode other than `Nearest`, consider using
662    /// [`Float::hypot_prec_round_val_ref`] instead. If you know that your target precision is the
663    /// maximum of the precisions of the two inputs, consider using [`Float::hypot`] instead.
664    ///
665    /// # Worst-case complexity
666    /// $T(n, m) = O((n + m) \log (n + m) \log\log (n + m))$
667    ///
668    /// $M(n, m) = O(n + m)$
669    ///
670    /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
671    /// `max(self.significant_bits(), other.significant_bits())`.
672    ///
673    /// # Panics
674    /// Panics if `prec` is zero.
675    ///
676    /// # Examples
677    /// ```
678    /// use core::f64::consts::{E, PI};
679    /// use malachite_float::Float;
680    /// use std::cmp::Ordering::*;
681    ///
682    /// let (hypot, o) = Float::from(PI).hypot_prec_val_ref(&Float::from(E), 5);
683    /// assert_eq!(hypot.to_string(), "4.25");
684    /// assert_eq!(o, Greater);
685    ///
686    /// let (hypot, o) = Float::from(PI).hypot_prec_val_ref(&Float::from(E), 20);
687    /// assert_eq!(hypot.to_string(), "4.1543579");
688    /// assert_eq!(o, Greater);
689    /// ```
690    #[inline]
691    pub fn hypot_prec_val_ref(self, other: &Self, prec: u64) -> (Self, Ordering) {
692        self.hypot_prec_round_val_ref(other, prec, Nearest)
693    }
694
695    /// Computes the hypotenuse of two [`Float`]s, $\sqrt{x^2+y^2}$, rounding the result to the
696    /// nearest value of the specified precision. The first [`Float`] is taken by reference and the
697    /// second by value. An [`Ordering`] is also returned, indicating whether the rounded hypotenuse
698    /// is less than, equal to, or greater than the exact hypotenuse. Although `NaN`s are not
699    /// comparable to any [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
700    ///
701    /// If the hypotenuse is equidistant from two [`Float`]s with the specified precision, the
702    /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
703    /// description of the `Nearest` rounding mode.
704    ///
705    /// $$
706    /// f(x,y,p) = \sqrt{x^2+y^2}+\varepsilon.
707    /// $$
708    /// - If $\sqrt{x^2+y^2}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
709    ///   to be 0.
710    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, then $|\varepsilon| \leq 2^{\lfloor\log_2
711    ///   \sqrt{x^2+y^2}\rfloor-p}$.
712    ///
713    /// If the output has a precision, it is `prec`.
714    ///
715    /// See the [`Float::hypot_prec_round`] documentation for information on special cases,
716    /// overflow, and underflow.
717    ///
718    /// If you want to use a rounding mode other than `Nearest`, consider using
719    /// [`Float::hypot_prec_round_ref_val`] instead. If you know that your target precision is the
720    /// maximum of the precisions of the two inputs, consider using [`Float::hypot`] instead.
721    ///
722    /// # Worst-case complexity
723    /// $T(n, m) = O((n + m) \log (n + m) \log\log (n + m))$
724    ///
725    /// $M(n, m) = O(n + m)$
726    ///
727    /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
728    /// `max(self.significant_bits(), other.significant_bits())`.
729    ///
730    /// # Panics
731    /// Panics if `prec` is zero.
732    ///
733    /// # Examples
734    /// ```
735    /// use core::f64::consts::{E, PI};
736    /// use malachite_float::Float;
737    /// use std::cmp::Ordering::*;
738    ///
739    /// let (hypot, o) = Float::from(PI).hypot_prec_ref_val(Float::from(E), 5);
740    /// assert_eq!(hypot.to_string(), "4.25");
741    /// assert_eq!(o, Greater);
742    ///
743    /// let (hypot, o) = Float::from(PI).hypot_prec_ref_val(Float::from(E), 20);
744    /// assert_eq!(hypot.to_string(), "4.1543579");
745    /// assert_eq!(o, Greater);
746    /// ```
747    #[inline]
748    pub fn hypot_prec_ref_val(&self, other: Self, prec: u64) -> (Self, Ordering) {
749        self.hypot_prec_round_ref_val(other, prec, Nearest)
750    }
751
752    /// Computes the hypotenuse of two [`Float`]s, $\sqrt{x^2+y^2}$, rounding the result to the
753    /// nearest value of the specified precision. Both [`Float`]s are taken by reference. An
754    /// [`Ordering`] is also returned, indicating whether the rounded hypotenuse is less than, equal
755    /// to, or greater than the exact hypotenuse. Although `NaN`s are not comparable to any
756    /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
757    ///
758    /// If the hypotenuse is equidistant from two [`Float`]s with the specified precision, the
759    /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
760    /// description of the `Nearest` rounding mode.
761    ///
762    /// $$
763    /// f(x,y,p) = \sqrt{x^2+y^2}+\varepsilon.
764    /// $$
765    /// - If $\sqrt{x^2+y^2}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
766    ///   to be 0.
767    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, then $|\varepsilon| \leq 2^{\lfloor\log_2
768    ///   \sqrt{x^2+y^2}\rfloor-p}$.
769    ///
770    /// If the output has a precision, it is `prec`.
771    ///
772    /// See the [`Float::hypot_prec_round`] documentation for information on special cases,
773    /// overflow, and underflow.
774    ///
775    /// If you want to use a rounding mode other than `Nearest`, consider using
776    /// [`Float::hypot_prec_round_ref_ref`] instead. If you know that your target precision is the
777    /// maximum of the precisions of the two inputs, consider using [`Float::hypot`] instead.
778    ///
779    /// # Worst-case complexity
780    /// $T(n, m) = O((n + m) \log (n + m) \log\log (n + m))$
781    ///
782    /// $M(n, m) = O(n + m)$
783    ///
784    /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
785    /// `max(self.significant_bits(), other.significant_bits())`.
786    ///
787    /// # Panics
788    /// Panics if `prec` is zero.
789    ///
790    /// # Examples
791    /// ```
792    /// use core::f64::consts::{E, PI};
793    /// use malachite_float::Float;
794    /// use std::cmp::Ordering::*;
795    ///
796    /// let (hypot, o) = Float::from(PI).hypot_prec_ref_ref(&Float::from(E), 5);
797    /// assert_eq!(hypot.to_string(), "4.25");
798    /// assert_eq!(o, Greater);
799    ///
800    /// let (hypot, o) = Float::from(PI).hypot_prec_ref_ref(&Float::from(E), 20);
801    /// assert_eq!(hypot.to_string(), "4.1543579");
802    /// assert_eq!(o, Greater);
803    /// ```
804    #[inline]
805    pub fn hypot_prec_ref_ref(&self, other: &Self, prec: u64) -> (Self, Ordering) {
806        self.hypot_prec_round_ref_ref(other, prec, Nearest)
807    }
808
809    /// Computes the hypotenuse of two [`Float`]s, $\sqrt{x^2+y^2}$, rounding the result with the
810    /// specified rounding mode. Both [`Float`]s are taken by value. An [`Ordering`] is also
811    /// returned, indicating whether the rounded hypotenuse is less than, equal to, or greater than
812    /// the exact hypotenuse. Although `NaN`s are not comparable to any [`Float`], whenever this
813    /// function returns a `NaN` it also returns `Equal`.
814    ///
815    /// The precision of the output is the maximum of the precision of the inputs. See
816    /// [`RoundingMode`] for a description of the possible rounding modes.
817    ///
818    /// $$
819    /// f(x,y,m) = \sqrt{x^2+y^2}+\varepsilon.
820    /// $$
821    /// - If $\sqrt{x^2+y^2}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
822    ///   to be 0.
823    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
824    ///   2^{\lfloor\log_2 \sqrt{x^2+y^2}\rfloor-p+1}$, where $p$ is the maximum precision of the
825    ///   inputs.
826    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
827    ///   2^{\lfloor\log_2 \sqrt{x^2+y^2}\rfloor-p}$, where $p$ is the maximum precision of the
828    ///   inputs.
829    ///
830    /// See the [`Float::hypot_prec_round`] documentation for information on special cases,
831    /// overflow, and underflow.
832    ///
833    /// If you want to specify an output precision, consider using [`Float::hypot_prec_round`]
834    /// instead. If you know you'll be using the `Nearest` rounding mode, consider using
835    /// [`Float::hypot`] instead.
836    ///
837    /// # Worst-case complexity
838    /// $T(n) = O(n \log n \log\log n)$
839    ///
840    /// $M(n) = O(n)$
841    ///
842    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
843    /// other.significant_bits())`.
844    ///
845    /// # Panics
846    /// Panics if `rm` is `Exact` and the hypotenuse is not exactly representable with the maximum
847    /// of the precisions of the inputs.
848    ///
849    /// # Examples
850    /// ```
851    /// use core::f64::consts::{E, PI};
852    /// use malachite_base::rounding_modes::RoundingMode::*;
853    /// use malachite_float::Float;
854    /// use std::cmp::Ordering::*;
855    ///
856    /// let (hypot, o) = Float::from(PI).hypot_round(Float::from(E), Floor);
857    /// assert_eq!(hypot.to_string(), "4.1543544023133130");
858    /// assert_eq!(o, Less);
859    ///
860    /// let (hypot, o) = Float::from(PI).hypot_round(Float::from(E), Ceiling);
861    /// assert_eq!(hypot.to_string(), "4.1543544023133139");
862    /// assert_eq!(o, Greater);
863    ///
864    /// let (hypot, o) = Float::from(PI).hypot_round(Float::from(E), Nearest);
865    /// assert_eq!(hypot.to_string(), "4.1543544023133130");
866    /// assert_eq!(o, Less);
867    /// ```
868    #[inline]
869    pub fn hypot_round(self, other: Self, rm: RoundingMode) -> (Self, Ordering) {
870        let prec = max(self.significant_bits(), other.significant_bits());
871        self.hypot_prec_round(other, prec, rm)
872    }
873
874    /// Computes the hypotenuse of two [`Float`]s, $\sqrt{x^2+y^2}$, rounding the result with the
875    /// specified rounding mode. The first [`Float`] is taken by value and the second by reference.
876    /// An [`Ordering`] is also returned, indicating whether the rounded hypotenuse is less than,
877    /// equal to, or greater than the exact hypotenuse. Although `NaN`s are not comparable to any
878    /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
879    ///
880    /// The precision of the output is the maximum of the precision of the inputs. See
881    /// [`RoundingMode`] for a description of the possible rounding modes.
882    ///
883    /// $$
884    /// f(x,y,m) = \sqrt{x^2+y^2}+\varepsilon.
885    /// $$
886    /// - If $\sqrt{x^2+y^2}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
887    ///   to be 0.
888    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
889    ///   2^{\lfloor\log_2 \sqrt{x^2+y^2}\rfloor-p+1}$, where $p$ is the maximum precision of the
890    ///   inputs.
891    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
892    ///   2^{\lfloor\log_2 \sqrt{x^2+y^2}\rfloor-p}$, where $p$ is the maximum precision of the
893    ///   inputs.
894    ///
895    /// See the [`Float::hypot_prec_round`] documentation for information on special cases,
896    /// overflow, and underflow.
897    ///
898    /// If you want to specify an output precision, consider using
899    /// [`Float::hypot_prec_round_val_ref`] instead. If you know you'll be using the `Nearest`
900    /// rounding mode, consider using [`Float::hypot`] instead.
901    ///
902    /// # Worst-case complexity
903    /// $T(n) = O(n \log n \log\log n)$
904    ///
905    /// $M(n) = O(n)$
906    ///
907    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
908    /// other.significant_bits())`.
909    ///
910    /// # Panics
911    /// Panics if `rm` is `Exact` and the hypotenuse is not exactly representable with the maximum
912    /// of the precisions of the inputs.
913    ///
914    /// # Examples
915    /// ```
916    /// use core::f64::consts::{E, PI};
917    /// use malachite_base::rounding_modes::RoundingMode::*;
918    /// use malachite_float::Float;
919    /// use std::cmp::Ordering::*;
920    ///
921    /// let (hypot, o) = Float::from(PI).hypot_round_val_ref(&Float::from(E), Floor);
922    /// assert_eq!(hypot.to_string(), "4.1543544023133130");
923    /// assert_eq!(o, Less);
924    ///
925    /// let (hypot, o) = Float::from(PI).hypot_round_val_ref(&Float::from(E), Ceiling);
926    /// assert_eq!(hypot.to_string(), "4.1543544023133139");
927    /// assert_eq!(o, Greater);
928    ///
929    /// let (hypot, o) = Float::from(PI).hypot_round_val_ref(&Float::from(E), Nearest);
930    /// assert_eq!(hypot.to_string(), "4.1543544023133130");
931    /// assert_eq!(o, Less);
932    /// ```
933    #[inline]
934    pub fn hypot_round_val_ref(self, other: &Self, rm: RoundingMode) -> (Self, Ordering) {
935        let prec = max(self.significant_bits(), other.significant_bits());
936        self.hypot_prec_round_val_ref(other, prec, rm)
937    }
938
939    /// Computes the hypotenuse of two [`Float`]s, $\sqrt{x^2+y^2}$, rounding the result with the
940    /// specified rounding mode. The first [`Float`] is taken by reference and the second by value.
941    /// An [`Ordering`] is also returned, indicating whether the rounded hypotenuse is less than,
942    /// equal to, or greater than the exact hypotenuse. Although `NaN`s are not comparable to any
943    /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
944    ///
945    /// The precision of the output is the maximum of the precision of the inputs. See
946    /// [`RoundingMode`] for a description of the possible rounding modes.
947    ///
948    /// $$
949    /// f(x,y,m) = \sqrt{x^2+y^2}+\varepsilon.
950    /// $$
951    /// - If $\sqrt{x^2+y^2}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
952    ///   to be 0.
953    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
954    ///   2^{\lfloor\log_2 \sqrt{x^2+y^2}\rfloor-p+1}$, where $p$ is the maximum precision of the
955    ///   inputs.
956    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
957    ///   2^{\lfloor\log_2 \sqrt{x^2+y^2}\rfloor-p}$, where $p$ is the maximum precision of the
958    ///   inputs.
959    ///
960    /// See the [`Float::hypot_prec_round`] documentation for information on special cases,
961    /// overflow, and underflow.
962    ///
963    /// If you want to specify an output precision, consider using
964    /// [`Float::hypot_prec_round_ref_val`] instead. If you know you'll be using the `Nearest`
965    /// rounding mode, consider using [`Float::hypot`] instead.
966    ///
967    /// # Worst-case complexity
968    /// $T(n) = O(n \log n \log\log n)$
969    ///
970    /// $M(n) = O(n)$
971    ///
972    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
973    /// other.significant_bits())`.
974    ///
975    /// # Panics
976    /// Panics if `rm` is `Exact` and the hypotenuse is not exactly representable with the maximum
977    /// of the precisions of the inputs.
978    ///
979    /// # Examples
980    /// ```
981    /// use core::f64::consts::{E, PI};
982    /// use malachite_base::rounding_modes::RoundingMode::*;
983    /// use malachite_float::Float;
984    /// use std::cmp::Ordering::*;
985    ///
986    /// let (hypot, o) = Float::from(PI).hypot_round_ref_val(Float::from(E), Floor);
987    /// assert_eq!(hypot.to_string(), "4.1543544023133130");
988    /// assert_eq!(o, Less);
989    ///
990    /// let (hypot, o) = Float::from(PI).hypot_round_ref_val(Float::from(E), Ceiling);
991    /// assert_eq!(hypot.to_string(), "4.1543544023133139");
992    /// assert_eq!(o, Greater);
993    ///
994    /// let (hypot, o) = Float::from(PI).hypot_round_ref_val(Float::from(E), Nearest);
995    /// assert_eq!(hypot.to_string(), "4.1543544023133130");
996    /// assert_eq!(o, Less);
997    /// ```
998    #[inline]
999    pub fn hypot_round_ref_val(&self, other: Self, rm: RoundingMode) -> (Self, Ordering) {
1000        let prec = max(self.significant_bits(), other.significant_bits());
1001        self.hypot_prec_round_ref_val(other, prec, rm)
1002    }
1003
1004    /// Computes the hypotenuse of two [`Float`]s, $\sqrt{x^2+y^2}$, rounding the result with the
1005    /// specified rounding mode. Both [`Float`]s are taken by reference. An [`Ordering`] is also
1006    /// returned, indicating whether the rounded hypotenuse is less than, equal to, or greater than
1007    /// the exact hypotenuse. Although `NaN`s are not comparable to any [`Float`], whenever this
1008    /// function returns a `NaN` it also returns `Equal`.
1009    ///
1010    /// The precision of the output is the maximum of the precision of the inputs. See
1011    /// [`RoundingMode`] for a description of the possible rounding modes.
1012    ///
1013    /// $$
1014    /// f(x,y,m) = \sqrt{x^2+y^2}+\varepsilon.
1015    /// $$
1016    /// - If $\sqrt{x^2+y^2}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
1017    ///   to be 0.
1018    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
1019    ///   2^{\lfloor\log_2 \sqrt{x^2+y^2}\rfloor-p+1}$, where $p$ is the maximum precision of the
1020    ///   inputs.
1021    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
1022    ///   2^{\lfloor\log_2 \sqrt{x^2+y^2}\rfloor-p}$, where $p$ is the maximum precision of the
1023    ///   inputs.
1024    ///
1025    /// See the [`Float::hypot_prec_round`] documentation for information on special cases,
1026    /// overflow, and underflow.
1027    ///
1028    /// If you want to specify an output precision, consider using
1029    /// [`Float::hypot_prec_round_ref_ref`] instead. If you know you'll be using the `Nearest`
1030    /// rounding mode, consider using [`Float::hypot`] instead.
1031    ///
1032    /// # Worst-case complexity
1033    /// $T(n) = O(n \log n \log\log n)$
1034    ///
1035    /// $M(n) = O(n)$
1036    ///
1037    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
1038    /// other.significant_bits())`.
1039    ///
1040    /// # Panics
1041    /// Panics if `rm` is `Exact` and the hypotenuse is not exactly representable with the maximum
1042    /// of the precisions of the inputs.
1043    ///
1044    /// # Examples
1045    /// ```
1046    /// use core::f64::consts::{E, PI};
1047    /// use malachite_base::rounding_modes::RoundingMode::*;
1048    /// use malachite_float::Float;
1049    /// use std::cmp::Ordering::*;
1050    ///
1051    /// let (hypot, o) = Float::from(PI).hypot_round_ref_ref(&Float::from(E), Floor);
1052    /// assert_eq!(hypot.to_string(), "4.1543544023133130");
1053    /// assert_eq!(o, Less);
1054    ///
1055    /// let (hypot, o) = Float::from(PI).hypot_round_ref_ref(&Float::from(E), Ceiling);
1056    /// assert_eq!(hypot.to_string(), "4.1543544023133139");
1057    /// assert_eq!(o, Greater);
1058    ///
1059    /// let (hypot, o) = Float::from(PI).hypot_round_ref_ref(&Float::from(E), Nearest);
1060    /// assert_eq!(hypot.to_string(), "4.1543544023133130");
1061    /// assert_eq!(o, Less);
1062    /// ```
1063    #[inline]
1064    pub fn hypot_round_ref_ref(&self, other: &Self, rm: RoundingMode) -> (Self, Ordering) {
1065        let prec = max(self.significant_bits(), other.significant_bits());
1066        self.hypot_prec_round_ref_ref(other, prec, rm)
1067    }
1068
1069    /// Computes the hypotenuse of two [`Float`]s, $\sqrt{x^2+y^2}$, mutating the first one in
1070    /// place, and rounding the result to the specified precision and with the specified rounding
1071    /// mode. The [`Float`] on the right-hand side is taken by value. An [`Ordering`] is returned,
1072    /// indicating whether the rounded hypotenuse is less than, equal to, or greater than the exact
1073    /// hypotenuse. Although `NaN`s are not comparable to any [`Float`], whenever this function sets
1074    /// the [`Float`] to `NaN` it also returns `Equal`.
1075    ///
1076    /// See [`RoundingMode`] for a description of the possible rounding modes.
1077    ///
1078    /// $$
1079    /// x \gets \sqrt{x^2+y^2}+\varepsilon.
1080    /// $$
1081    /// - If $\sqrt{x^2+y^2}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
1082    ///   to be 0.
1083    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
1084    ///   2^{\lfloor\log_2 \sqrt{x^2+y^2}\rfloor-p+1}$.
1085    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
1086    ///   2^{\lfloor\log_2 \sqrt{x^2+y^2}\rfloor-p}$.
1087    ///
1088    /// If the output has a precision, it is `prec`.
1089    ///
1090    /// See the [`Float::hypot_prec_round`] documentation for information on special cases,
1091    /// overflow, and underflow.
1092    ///
1093    /// If you know you'll be using `Nearest`, consider using [`Float::hypot_prec_assign`] instead.
1094    /// If you know that your target precision is the maximum of the precisions of the two inputs,
1095    /// consider using [`Float::hypot_round_assign`] instead. If both of these things are true,
1096    /// consider using [`Float::hypot`] instead.
1097    ///
1098    /// # Worst-case complexity
1099    /// $T(n, m) = O((n + m) \log (n + m) \log\log (n + m))$
1100    ///
1101    /// $M(n, m) = O(n + m)$
1102    ///
1103    /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
1104    /// `max(self.significant_bits(), other.significant_bits())`.
1105    ///
1106    /// # Panics
1107    /// Panics if `prec` is zero, or if `rm` is `Exact` and the hypotenuse is not exactly
1108    /// representable with `prec` bits.
1109    ///
1110    /// # Examples
1111    /// ```
1112    /// use malachite_base::num::basic::traits::{One, Two};
1113    /// use malachite_base::rounding_modes::RoundingMode::*;
1114    /// use malachite_float::Float;
1115    /// use std::cmp::Ordering::*;
1116    ///
1117    /// let mut x = Float::ONE;
1118    /// assert_eq!(x.hypot_prec_round_assign(Float::TWO, 5, Floor), Less);
1119    /// assert_eq!(x.to_string(), "2.12");
1120    ///
1121    /// let mut x = Float::ONE;
1122    /// assert_eq!(x.hypot_prec_round_assign(Float::TWO, 5, Ceiling), Greater);
1123    /// assert_eq!(x.to_string(), "2.25");
1124    ///
1125    /// let mut x = Float::ONE;
1126    /// assert_eq!(x.hypot_prec_round_assign(Float::TWO, 5, Nearest), Greater);
1127    /// assert_eq!(x.to_string(), "2.25");
1128    ///
1129    /// let mut x = Float::ONE;
1130    /// assert_eq!(x.hypot_prec_round_assign(Float::TWO, 20, Floor), Less);
1131    /// assert_eq!(x.to_string(), "2.2360649");
1132    ///
1133    /// let mut x = Float::ONE;
1134    /// assert_eq!(x.hypot_prec_round_assign(Float::TWO, 20, Ceiling), Greater);
1135    /// assert_eq!(x.to_string(), "2.2360687");
1136    ///
1137    /// let mut x = Float::ONE;
1138    /// assert_eq!(x.hypot_prec_round_assign(Float::TWO, 20, Nearest), Greater);
1139    /// assert_eq!(x.to_string(), "2.2360687");
1140    /// ```
1141    pub fn hypot_prec_round_assign(
1142        &mut self,
1143        other: Self,
1144        prec: u64,
1145        rm: RoundingMode,
1146    ) -> Ordering {
1147        let o;
1148        let mut x = Self::ZERO;
1149        swap(&mut x, self);
1150        (*self, o) = x.hypot_prec_round(other, prec, rm);
1151        o
1152    }
1153
1154    /// Computes the hypotenuse of two [`Float`]s, $\sqrt{x^2+y^2}$, mutating the first one in
1155    /// place, and rounding the result to the specified precision and with the specified rounding
1156    /// mode. The [`Float`] on the right-hand side is taken by reference. An [`Ordering`] is
1157    /// returned, indicating whether the rounded hypotenuse is less than, equal to, or greater than
1158    /// the exact hypotenuse. Although `NaN`s are not comparable to any [`Float`], whenever this
1159    /// function sets the [`Float`] to `NaN` it also returns `Equal`.
1160    ///
1161    /// See [`RoundingMode`] for a description of the possible rounding modes.
1162    ///
1163    /// $$
1164    /// x \gets \sqrt{x^2+y^2}+\varepsilon.
1165    /// $$
1166    /// - If $\sqrt{x^2+y^2}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
1167    ///   to be 0.
1168    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
1169    ///   2^{\lfloor\log_2 \sqrt{x^2+y^2}\rfloor-p+1}$.
1170    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
1171    ///   2^{\lfloor\log_2 \sqrt{x^2+y^2}\rfloor-p}$.
1172    ///
1173    /// If the output has a precision, it is `prec`.
1174    ///
1175    /// See the [`Float::hypot_prec_round`] documentation for information on special cases,
1176    /// overflow, and underflow.
1177    ///
1178    /// If you know you'll be using `Nearest`, consider using [`Float::hypot_prec_assign_ref`]
1179    /// instead. If you know that your target precision is the maximum of the precisions of the two
1180    /// inputs, consider using [`Float::hypot_round_assign_ref`] instead. If both of these things
1181    /// are true, consider using [`Float::hypot`] instead.
1182    ///
1183    /// # Worst-case complexity
1184    /// $T(n, m) = O((n + m) \log (n + m) \log\log (n + m))$
1185    ///
1186    /// $M(n, m) = O(n + m)$
1187    ///
1188    /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
1189    /// `max(self.significant_bits(), other.significant_bits())`.
1190    ///
1191    /// # Panics
1192    /// Panics if `prec` is zero, or if `rm` is `Exact` and the hypotenuse is not exactly
1193    /// representable with `prec` bits.
1194    ///
1195    /// # Examples
1196    /// ```
1197    /// use malachite_base::num::basic::traits::{One, Two};
1198    /// use malachite_base::rounding_modes::RoundingMode::*;
1199    /// use malachite_float::Float;
1200    /// use std::cmp::Ordering::*;
1201    ///
1202    /// let mut x = Float::ONE;
1203    /// assert_eq!(x.hypot_prec_round_assign_ref(&Float::TWO, 5, Floor), Less);
1204    /// assert_eq!(x.to_string(), "2.12");
1205    ///
1206    /// let mut x = Float::ONE;
1207    /// assert_eq!(
1208    ///     x.hypot_prec_round_assign_ref(&Float::TWO, 5, Ceiling),
1209    ///     Greater
1210    /// );
1211    /// assert_eq!(x.to_string(), "2.25");
1212    ///
1213    /// let mut x = Float::ONE;
1214    /// assert_eq!(
1215    ///     x.hypot_prec_round_assign_ref(&Float::TWO, 5, Nearest),
1216    ///     Greater
1217    /// );
1218    /// assert_eq!(x.to_string(), "2.25");
1219    ///
1220    /// let mut x = Float::ONE;
1221    /// assert_eq!(x.hypot_prec_round_assign_ref(&Float::TWO, 20, Floor), Less);
1222    /// assert_eq!(x.to_string(), "2.2360649");
1223    ///
1224    /// let mut x = Float::ONE;
1225    /// assert_eq!(
1226    ///     x.hypot_prec_round_assign_ref(&Float::TWO, 20, Ceiling),
1227    ///     Greater
1228    /// );
1229    /// assert_eq!(x.to_string(), "2.2360687");
1230    ///
1231    /// let mut x = Float::ONE;
1232    /// assert_eq!(
1233    ///     x.hypot_prec_round_assign_ref(&Float::TWO, 20, Nearest),
1234    ///     Greater
1235    /// );
1236    /// assert_eq!(x.to_string(), "2.2360687");
1237    /// ```
1238    pub fn hypot_prec_round_assign_ref(
1239        &mut self,
1240        other: &Self,
1241        prec: u64,
1242        rm: RoundingMode,
1243    ) -> Ordering {
1244        let o;
1245        let mut x = Self::ZERO;
1246        swap(&mut x, self);
1247        (*self, o) = x.hypot_prec_round_val_ref(other, prec, rm);
1248        o
1249    }
1250
1251    /// Computes the hypotenuse of two [`Float`]s, $\sqrt{x^2+y^2}$, mutating the first one in
1252    /// place, and rounding the result to the nearest value of the specified precision. The
1253    /// [`Float`] on the right-hand side is taken by value. An [`Ordering`] is returned, indicating
1254    /// whether the rounded hypotenuse is less than, equal to, or greater than the exact hypotenuse.
1255    /// Although `NaN`s are not comparable to any [`Float`], whenever this function sets the
1256    /// [`Float`] to `NaN` it also returns `Equal`.
1257    ///
1258    /// If the hypotenuse is equidistant from two [`Float`]s with the specified precision, the
1259    /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
1260    /// description of the `Nearest` rounding mode.
1261    ///
1262    /// $$
1263    /// x \gets \sqrt{x^2+y^2}+\varepsilon.
1264    /// $$
1265    /// - If $\sqrt{x^2+y^2}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
1266    ///   to be 0.
1267    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, then $|\varepsilon| \leq 2^{\lfloor\log_2
1268    ///   \sqrt{x^2+y^2}\rfloor-p}$.
1269    ///
1270    /// If the output has a precision, it is `prec`.
1271    ///
1272    /// See the [`Float::hypot_prec_round`] documentation for information on special cases,
1273    /// overflow, and underflow.
1274    ///
1275    /// If you want to use a rounding mode other than `Nearest`, consider using
1276    /// [`Float::hypot_prec_round_assign`] instead. If you know that your target precision is the
1277    /// maximum of the precisions of the two inputs, consider using [`Float::hypot_assign`] instead.
1278    ///
1279    /// # Worst-case complexity
1280    /// $T(n, m) = O((n + m) \log (n + m) \log\log (n + m))$
1281    ///
1282    /// $M(n, m) = O(n + m)$
1283    ///
1284    /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
1285    /// `max(self.significant_bits(), other.significant_bits())`.
1286    ///
1287    /// # Panics
1288    /// Panics if `prec` is zero.
1289    ///
1290    /// # Examples
1291    /// ```
1292    /// use core::f64::consts::{E, PI};
1293    /// use malachite_float::Float;
1294    /// use std::cmp::Ordering::*;
1295    ///
1296    /// let mut x = Float::from(PI);
1297    /// assert_eq!(x.hypot_prec_assign(Float::from(E), 5), Greater);
1298    /// assert_eq!(x.to_string(), "4.25");
1299    ///
1300    /// let mut x = Float::from(PI);
1301    /// assert_eq!(x.hypot_prec_assign(Float::from(E), 20), Greater);
1302    /// assert_eq!(x.to_string(), "4.1543579");
1303    /// ```
1304    #[inline]
1305    pub fn hypot_prec_assign(&mut self, other: Self, prec: u64) -> Ordering {
1306        self.hypot_prec_round_assign(other, prec, Nearest)
1307    }
1308
1309    /// Computes the hypotenuse of two [`Float`]s, $\sqrt{x^2+y^2}$, mutating the first one in
1310    /// place, and rounding the result to the nearest value of the specified precision. The
1311    /// [`Float`] on the right-hand side is taken by reference. An [`Ordering`] is returned,
1312    /// indicating whether the rounded hypotenuse is less than, equal to, or greater than the exact
1313    /// hypotenuse. Although `NaN`s are not comparable to any [`Float`], whenever this function sets
1314    /// the [`Float`] to `NaN` it also returns `Equal`.
1315    ///
1316    /// If the hypotenuse is equidistant from two [`Float`]s with the specified precision, the
1317    /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
1318    /// description of the `Nearest` rounding mode.
1319    ///
1320    /// $$
1321    /// x \gets \sqrt{x^2+y^2}+\varepsilon.
1322    /// $$
1323    /// - If $\sqrt{x^2+y^2}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
1324    ///   to be 0.
1325    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, then $|\varepsilon| \leq 2^{\lfloor\log_2
1326    ///   \sqrt{x^2+y^2}\rfloor-p}$.
1327    ///
1328    /// If the output has a precision, it is `prec`.
1329    ///
1330    /// See the [`Float::hypot_prec_round`] documentation for information on special cases,
1331    /// overflow, and underflow.
1332    ///
1333    /// If you want to use a rounding mode other than `Nearest`, consider using
1334    /// [`Float::hypot_prec_round_assign_ref`] instead. If you know that your target precision is
1335    /// the maximum of the precisions of the two inputs, consider using [`Float::hypot_assign`]
1336    /// instead.
1337    ///
1338    /// # Worst-case complexity
1339    /// $T(n, m) = O((n + m) \log (n + m) \log\log (n + m))$
1340    ///
1341    /// $M(n, m) = O(n + m)$
1342    ///
1343    /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
1344    /// `max(self.significant_bits(), other.significant_bits())`.
1345    ///
1346    /// # Panics
1347    /// Panics if `prec` is zero.
1348    ///
1349    /// # Examples
1350    /// ```
1351    /// use core::f64::consts::{E, PI};
1352    /// use malachite_float::Float;
1353    /// use std::cmp::Ordering::*;
1354    ///
1355    /// let mut x = Float::from(PI);
1356    /// assert_eq!(x.hypot_prec_assign_ref(&Float::from(E), 5), Greater);
1357    /// assert_eq!(x.to_string(), "4.25");
1358    ///
1359    /// let mut x = Float::from(PI);
1360    /// assert_eq!(x.hypot_prec_assign_ref(&Float::from(E), 20), Greater);
1361    /// assert_eq!(x.to_string(), "4.1543579");
1362    /// ```
1363    #[inline]
1364    pub fn hypot_prec_assign_ref(&mut self, other: &Self, prec: u64) -> Ordering {
1365        self.hypot_prec_round_assign_ref(other, prec, Nearest)
1366    }
1367
1368    /// Computes the hypotenuse of two [`Float`]s, $\sqrt{x^2+y^2}$, mutating the first one in
1369    /// place, and rounding the result with the specified rounding mode. The [`Float`] on the
1370    /// right-hand side is taken by value. An [`Ordering`] is returned, indicating whether the
1371    /// rounded hypotenuse is less than, equal to, or greater than the exact hypotenuse. Although
1372    /// `NaN`s are not comparable to any [`Float`], whenever this function sets the [`Float`] to
1373    /// `NaN` it also returns `Equal`.
1374    ///
1375    /// The precision of the output is the maximum of the precision of the inputs. See
1376    /// [`RoundingMode`] for a description of the possible rounding modes.
1377    ///
1378    /// $$
1379    /// x \gets \sqrt{x^2+y^2}+\varepsilon.
1380    /// $$
1381    /// - If $\sqrt{x^2+y^2}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
1382    ///   to be 0.
1383    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
1384    ///   2^{\lfloor\log_2 \sqrt{x^2+y^2}\rfloor-p+1}$, where $p$ is the maximum precision of the
1385    ///   inputs.
1386    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
1387    ///   2^{\lfloor\log_2 \sqrt{x^2+y^2}\rfloor-p}$, where $p$ is the maximum precision of the
1388    ///   inputs.
1389    ///
1390    /// See the [`Float::hypot_prec_round`] documentation for information on special cases,
1391    /// overflow, and underflow.
1392    ///
1393    /// If you want to specify an output precision, consider using
1394    /// [`Float::hypot_prec_round_assign`] instead. If you know you'll be using the `Nearest`
1395    /// rounding mode, consider using [`Float::hypot_assign`] instead.
1396    ///
1397    /// # Worst-case complexity
1398    /// $T(n) = O(n \log n \log\log n)$
1399    ///
1400    /// $M(n) = O(n)$
1401    ///
1402    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
1403    /// other.significant_bits())`.
1404    ///
1405    /// # Panics
1406    /// Panics if `rm` is `Exact` and the hypotenuse is not exactly representable with the maximum
1407    /// of the precisions of the inputs.
1408    ///
1409    /// # Examples
1410    /// ```
1411    /// use core::f64::consts::{E, PI};
1412    /// use malachite_base::rounding_modes::RoundingMode::*;
1413    /// use malachite_float::Float;
1414    /// use std::cmp::Ordering::*;
1415    ///
1416    /// let mut x = Float::from(PI);
1417    /// assert_eq!(x.hypot_round_assign(Float::from(E), Floor), Less);
1418    /// assert_eq!(x.to_string(), "4.1543544023133130");
1419    ///
1420    /// let mut x = Float::from(PI);
1421    /// assert_eq!(x.hypot_round_assign(Float::from(E), Ceiling), Greater);
1422    /// assert_eq!(x.to_string(), "4.1543544023133139");
1423    ///
1424    /// let mut x = Float::from(PI);
1425    /// assert_eq!(x.hypot_round_assign(Float::from(E), Nearest), Less);
1426    /// assert_eq!(x.to_string(), "4.1543544023133130");
1427    /// ```
1428    #[inline]
1429    pub fn hypot_round_assign(&mut self, other: Self, rm: RoundingMode) -> Ordering {
1430        let prec = max(self.significant_bits(), other.significant_bits());
1431        self.hypot_prec_round_assign(other, prec, rm)
1432    }
1433
1434    /// Computes the hypotenuse of two [`Float`]s, $\sqrt{x^2+y^2}$, mutating the first one in
1435    /// place, and rounding the result with the specified rounding mode. The [`Float`] on the
1436    /// right-hand side is taken by reference. An [`Ordering`] is returned, indicating whether the
1437    /// rounded hypotenuse is less than, equal to, or greater than the exact hypotenuse. Although
1438    /// `NaN`s are not comparable to any [`Float`], whenever this function sets the [`Float`] to
1439    /// `NaN` it also returns `Equal`.
1440    ///
1441    /// The precision of the output is the maximum of the precision of the inputs. See
1442    /// [`RoundingMode`] for a description of the possible rounding modes.
1443    ///
1444    /// $$
1445    /// x \gets \sqrt{x^2+y^2}+\varepsilon.
1446    /// $$
1447    /// - If $\sqrt{x^2+y^2}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
1448    ///   to be 0.
1449    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
1450    ///   2^{\lfloor\log_2 \sqrt{x^2+y^2}\rfloor-p+1}$, where $p$ is the maximum precision of the
1451    ///   inputs.
1452    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
1453    ///   2^{\lfloor\log_2 \sqrt{x^2+y^2}\rfloor-p}$, where $p$ is the maximum precision of the
1454    ///   inputs.
1455    ///
1456    /// See the [`Float::hypot_prec_round`] documentation for information on special cases,
1457    /// overflow, and underflow.
1458    ///
1459    /// If you want to specify an output precision, consider using
1460    /// [`Float::hypot_prec_round_assign_ref`] instead. If you know you'll be using the `Nearest`
1461    /// rounding mode, consider using [`Float::hypot_assign`] instead.
1462    ///
1463    /// # Worst-case complexity
1464    /// $T(n) = O(n \log n \log\log n)$
1465    ///
1466    /// $M(n) = O(n)$
1467    ///
1468    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
1469    /// other.significant_bits())`.
1470    ///
1471    /// # Panics
1472    /// Panics if `rm` is `Exact` and the hypotenuse is not exactly representable with the maximum
1473    /// of the precisions of the inputs.
1474    ///
1475    /// # Examples
1476    /// ```
1477    /// use core::f64::consts::{E, PI};
1478    /// use malachite_base::rounding_modes::RoundingMode::*;
1479    /// use malachite_float::Float;
1480    /// use std::cmp::Ordering::*;
1481    ///
1482    /// let mut x = Float::from(PI);
1483    /// assert_eq!(x.hypot_round_assign_ref(&Float::from(E), Floor), Less);
1484    /// assert_eq!(x.to_string(), "4.1543544023133130");
1485    ///
1486    /// let mut x = Float::from(PI);
1487    /// assert_eq!(x.hypot_round_assign_ref(&Float::from(E), Ceiling), Greater);
1488    /// assert_eq!(x.to_string(), "4.1543544023133139");
1489    ///
1490    /// let mut x = Float::from(PI);
1491    /// assert_eq!(x.hypot_round_assign_ref(&Float::from(E), Nearest), Less);
1492    /// assert_eq!(x.to_string(), "4.1543544023133130");
1493    /// ```
1494    #[inline]
1495    pub fn hypot_round_assign_ref(&mut self, other: &Self, rm: RoundingMode) -> Ordering {
1496        let prec = max(self.significant_bits(), other.significant_bits());
1497        self.hypot_prec_round_assign_ref(other, prec, rm)
1498    }
1499}
1500
1501impl Hypot<Self> for Float {
1502    type Output = Self;
1503
1504    /// Computes the hypotenuse of two [`Float`]s, $\sqrt{x^2+y^2}$. Both [`Float`]s are taken by
1505    /// value.
1506    ///
1507    /// The precision of the output is the maximum of the precision of the inputs. If the hypotenuse
1508    /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s
1509    /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
1510    /// rounding mode.
1511    ///
1512    /// $$
1513    /// f(x,y) = \sqrt{x^2+y^2}+\varepsilon.
1514    /// $$
1515    /// - If $\sqrt{x^2+y^2}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
1516    ///   to be 0.
1517    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, then $|\varepsilon| \leq 2^{\lfloor\log_2
1518    ///   \sqrt{x^2+y^2}\rfloor-p}$, where $p$ is the maximum precision of the inputs.
1519    ///
1520    /// Special cases:
1521    /// - $f(\pm\infty,x)=f(x,\pm\infty)=\infty$, even when the other argument is `NaN`
1522    /// - $f(\text{NaN},x)=f(x,\text{NaN})=\text{NaN}$ if $x$ is not infinite
1523    /// - $f(\pm0.0,\pm0.0)=0.0$
1524    ///
1525    /// The result is never negative, and a zero result is always positive.
1526    ///
1527    /// See the [`Float::hypot_prec_round`] documentation for information on overflow.
1528    ///
1529    /// # Worst-case complexity
1530    /// $T(n) = O(n \log n \log\log n)$
1531    ///
1532    /// $M(n) = O(n)$
1533    ///
1534    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
1535    /// other.significant_bits())`.
1536    ///
1537    /// # Examples
1538    /// ```
1539    /// use core::f64::consts::{E, PI};
1540    /// use malachite_base::num::arithmetic::traits::Hypot;
1541    /// use malachite_float::Float;
1542    ///
1543    /// assert_eq!(
1544    ///     Float::from(PI).hypot(Float::from(E)).to_string(),
1545    ///     "4.1543544023133130"
1546    /// );
1547    /// ```
1548    #[inline]
1549    fn hypot(self, other: Self) -> Self {
1550        let prec = max(self.significant_bits(), other.significant_bits());
1551        self.hypot_prec_round(other, prec, Nearest).0
1552    }
1553}
1554
1555impl Hypot<&Self> for Float {
1556    type Output = Self;
1557
1558    /// Computes the hypotenuse of two [`Float`]s, $\sqrt{x^2+y^2}$. The first [`Float`] is taken by
1559    /// value and the second by reference.
1560    ///
1561    /// The precision of the output is the maximum of the precision of the inputs. If the hypotenuse
1562    /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s
1563    /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
1564    /// rounding mode.
1565    ///
1566    /// $$
1567    /// f(x,y) = \sqrt{x^2+y^2}+\varepsilon.
1568    /// $$
1569    /// - If $\sqrt{x^2+y^2}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
1570    ///   to be 0.
1571    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, then $|\varepsilon| \leq 2^{\lfloor\log_2
1572    ///   \sqrt{x^2+y^2}\rfloor-p}$, where $p$ is the maximum precision of the inputs.
1573    ///
1574    /// Special cases:
1575    /// - $f(\pm\infty,x)=f(x,\pm\infty)=\infty$, even when the other argument is `NaN`
1576    /// - $f(\text{NaN},x)=f(x,\text{NaN})=\text{NaN}$ if $x$ is not infinite
1577    /// - $f(\pm0.0,\pm0.0)=0.0$
1578    ///
1579    /// The result is never negative, and a zero result is always positive.
1580    ///
1581    /// See the [`Float::hypot_prec_round`] documentation for information on overflow.
1582    ///
1583    /// # Worst-case complexity
1584    /// $T(n) = O(n \log n \log\log n)$
1585    ///
1586    /// $M(n) = O(n)$
1587    ///
1588    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
1589    /// other.significant_bits())`.
1590    ///
1591    /// # Examples
1592    /// ```
1593    /// use core::f64::consts::{E, PI};
1594    /// use malachite_base::num::arithmetic::traits::Hypot;
1595    /// use malachite_float::Float;
1596    ///
1597    /// assert_eq!(
1598    ///     Float::from(PI).hypot(&Float::from(E)).to_string(),
1599    ///     "4.1543544023133130"
1600    /// );
1601    /// ```
1602    #[inline]
1603    fn hypot(self, other: &Self) -> Self {
1604        let prec = max(self.significant_bits(), other.significant_bits());
1605        self.hypot_prec_round_val_ref(other, prec, Nearest).0
1606    }
1607}
1608
1609impl Hypot<Float> for &Float {
1610    type Output = Float;
1611
1612    /// Computes the hypotenuse of two [`Float`]s, $\sqrt{x^2+y^2}$. The first [`Float`] is taken by
1613    /// reference and the second by value.
1614    ///
1615    /// The precision of the output is the maximum of the precision of the inputs. If the hypotenuse
1616    /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s
1617    /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
1618    /// rounding mode.
1619    ///
1620    /// $$
1621    /// f(x,y) = \sqrt{x^2+y^2}+\varepsilon.
1622    /// $$
1623    /// - If $\sqrt{x^2+y^2}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
1624    ///   to be 0.
1625    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, then $|\varepsilon| \leq 2^{\lfloor\log_2
1626    ///   \sqrt{x^2+y^2}\rfloor-p}$, where $p$ is the maximum precision of the inputs.
1627    ///
1628    /// Special cases:
1629    /// - $f(\pm\infty,x)=f(x,\pm\infty)=\infty$, even when the other argument is `NaN`
1630    /// - $f(\text{NaN},x)=f(x,\text{NaN})=\text{NaN}$ if $x$ is not infinite
1631    /// - $f(\pm0.0,\pm0.0)=0.0$
1632    ///
1633    /// The result is never negative, and a zero result is always positive.
1634    ///
1635    /// See the [`Float::hypot_prec_round`] documentation for information on overflow.
1636    ///
1637    /// # Worst-case complexity
1638    /// $T(n) = O(n \log n \log\log n)$
1639    ///
1640    /// $M(n) = O(n)$
1641    ///
1642    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
1643    /// other.significant_bits())`.
1644    ///
1645    /// # Examples
1646    /// ```
1647    /// use core::f64::consts::{E, PI};
1648    /// use malachite_base::num::arithmetic::traits::Hypot;
1649    /// use malachite_float::Float;
1650    ///
1651    /// assert_eq!(
1652    ///     (&Float::from(PI)).hypot(Float::from(E)).to_string(),
1653    ///     "4.1543544023133130"
1654    /// );
1655    /// ```
1656    #[inline]
1657    fn hypot(self, other: Float) -> Float {
1658        let prec = max(self.significant_bits(), other.significant_bits());
1659        self.hypot_prec_round_ref_val(other, prec, Nearest).0
1660    }
1661}
1662
1663impl Hypot<&Float> for &Float {
1664    type Output = Float;
1665
1666    /// Computes the hypotenuse of two [`Float`]s, $\sqrt{x^2+y^2}$. Both [`Float`]s are taken by
1667    /// reference.
1668    ///
1669    /// The precision of the output is the maximum of the precision of the inputs. If the hypotenuse
1670    /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s
1671    /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
1672    /// rounding mode.
1673    ///
1674    /// $$
1675    /// f(x,y) = \sqrt{x^2+y^2}+\varepsilon.
1676    /// $$
1677    /// - If $\sqrt{x^2+y^2}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
1678    ///   to be 0.
1679    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, then $|\varepsilon| \leq 2^{\lfloor\log_2
1680    ///   \sqrt{x^2+y^2}\rfloor-p}$, where $p$ is the maximum precision of the inputs.
1681    ///
1682    /// Special cases:
1683    /// - $f(\pm\infty,x)=f(x,\pm\infty)=\infty$, even when the other argument is `NaN`
1684    /// - $f(\text{NaN},x)=f(x,\text{NaN})=\text{NaN}$ if $x$ is not infinite
1685    /// - $f(\pm0.0,\pm0.0)=0.0$
1686    ///
1687    /// The result is never negative, and a zero result is always positive.
1688    ///
1689    /// See the [`Float::hypot_prec_round`] documentation for information on overflow.
1690    ///
1691    /// # Worst-case complexity
1692    /// $T(n) = O(n \log n \log\log n)$
1693    ///
1694    /// $M(n) = O(n)$
1695    ///
1696    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
1697    /// other.significant_bits())`.
1698    ///
1699    /// # Examples
1700    /// ```
1701    /// use core::f64::consts::{E, PI};
1702    /// use malachite_base::num::arithmetic::traits::Hypot;
1703    /// use malachite_float::Float;
1704    ///
1705    /// assert_eq!(
1706    ///     (&Float::from(PI)).hypot(&Float::from(E)).to_string(),
1707    ///     "4.1543544023133130"
1708    /// );
1709    /// ```
1710    #[inline]
1711    fn hypot(self, other: &Float) -> Float {
1712        let prec = max(self.significant_bits(), other.significant_bits());
1713        self.hypot_prec_round_ref_ref(other, prec, Nearest).0
1714    }
1715}
1716
1717impl HypotAssign<Self> for Float {
1718    /// Replaces a [`Float`] with the hypotenuse of it and another [`Float`], $\sqrt{x^2+y^2}$. The
1719    /// [`Float`] on the right-hand side is taken by value.
1720    ///
1721    /// The precision of the output is the maximum of the precision of the inputs. If the hypotenuse
1722    /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s
1723    /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
1724    /// rounding mode.
1725    ///
1726    /// $$
1727    /// x \gets \sqrt{x^2+y^2}+\varepsilon.
1728    /// $$
1729    /// - If $\sqrt{x^2+y^2}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
1730    ///   to be 0.
1731    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, then $|\varepsilon| \leq 2^{\lfloor\log_2
1732    ///   \sqrt{x^2+y^2}\rfloor-p}$, where $p$ is the maximum precision of the inputs.
1733    ///
1734    /// See the [`Float::hypot_prec_round`] documentation for information on special cases,
1735    /// overflow, and underflow.
1736    ///
1737    /// # Worst-case complexity
1738    /// $T(n) = O(n \log n \log\log n)$
1739    ///
1740    /// $M(n) = O(n)$
1741    ///
1742    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
1743    /// other.significant_bits())`.
1744    ///
1745    /// # Examples
1746    /// ```
1747    /// use core::f64::consts::{E, PI};
1748    /// use malachite_base::num::arithmetic::traits::HypotAssign;
1749    /// use malachite_float::Float;
1750    ///
1751    /// let mut x = Float::from(PI);
1752    /// x.hypot_assign(Float::from(E));
1753    /// assert_eq!(x.to_string(), "4.1543544023133130");
1754    /// ```
1755    #[inline]
1756    fn hypot_assign(&mut self, other: Self) {
1757        let prec = max(self.significant_bits(), other.significant_bits());
1758        self.hypot_prec_round_assign(other, prec, Nearest);
1759    }
1760}
1761
1762impl HypotAssign<&Self> for Float {
1763    /// Replaces a [`Float`] with the hypotenuse of it and another [`Float`], $\sqrt{x^2+y^2}$. The
1764    /// [`Float`] on the right-hand side is taken by reference.
1765    ///
1766    /// The precision of the output is the maximum of the precision of the inputs. If the hypotenuse
1767    /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s
1768    /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
1769    /// rounding mode.
1770    ///
1771    /// $$
1772    /// x \gets \sqrt{x^2+y^2}+\varepsilon.
1773    /// $$
1774    /// - If $\sqrt{x^2+y^2}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
1775    ///   to be 0.
1776    /// - If $\sqrt{x^2+y^2}$ is finite and nonzero, then $|\varepsilon| \leq 2^{\lfloor\log_2
1777    ///   \sqrt{x^2+y^2}\rfloor-p}$, where $p$ is the maximum precision of the inputs.
1778    ///
1779    /// See the [`Float::hypot_prec_round`] documentation for information on special cases,
1780    /// overflow, and underflow.
1781    ///
1782    /// # Worst-case complexity
1783    /// $T(n) = O(n \log n \log\log n)$
1784    ///
1785    /// $M(n) = O(n)$
1786    ///
1787    /// where $T$ is time, $M$ is additional memory, and $n$ is `max(self.significant_bits(),
1788    /// other.significant_bits())`.
1789    ///
1790    /// # Examples
1791    /// ```
1792    /// use core::f64::consts::{E, PI};
1793    /// use malachite_base::num::arithmetic::traits::HypotAssign;
1794    /// use malachite_float::Float;
1795    ///
1796    /// let mut x = Float::from(PI);
1797    /// x.hypot_assign(&Float::from(E));
1798    /// assert_eq!(x.to_string(), "4.1543544023133130");
1799    /// ```
1800    #[inline]
1801    fn hypot_assign(&mut self, other: &Self) {
1802        let prec = max(self.significant_bits(), other.significant_bits());
1803        self.hypot_prec_round_assign_ref(other, prec, Nearest);
1804    }
1805}
1806
1807/// Computes the hypotenuse of two primitive floats, $\sqrt{x^2+y^2}$, with a single rounding.
1808///
1809/// $$
1810/// f(x,y) = \sqrt{x^2+y^2}+\varepsilon.
1811/// $$
1812/// - If $\sqrt{x^2+y^2}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be
1813///   0.
1814/// - If $\sqrt{x^2+y^2}$ is finite and nonzero, then $|\varepsilon| \leq 2^{\lfloor\log_2
1815///   \sqrt{x^2+y^2}\rfloor-p}$, where $p$ is the precision of the output (typically 24 if `T` is a
1816///   [`f32`] and 53 if `T` is a [`f64`], but less if the output is subnormal).
1817///
1818/// Special cases:
1819/// - $f(\pm\infty,x)=f(x,\pm\infty)=\infty$, even when the other argument is `NaN`
1820/// - $f(\text{NaN},x)=f(x,\text{NaN})=\text{NaN}$ if $x$ is not infinite
1821/// - $f(\pm0.0,\pm0.0)=0.0$
1822///
1823/// The result is never negative, and a zero result is always positive.
1824///
1825/// # Worst-case complexity
1826/// Constant time and additional memory.
1827///
1828/// # Examples
1829/// ```
1830/// use core::f64::consts::{E, PI};
1831/// use malachite_base::num::float::NiceFloat;
1832/// use malachite_float::float::arithmetic::hypot::primitive_float_hypot;
1833///
1834/// assert_eq!(
1835///     NiceFloat(primitive_float_hypot(PI, E)),
1836///     NiceFloat(4.154354402313313)
1837/// );
1838/// ```
1839#[allow(clippy::type_repetition_in_bounds)]
1840#[inline]
1841pub fn primitive_float_hypot<T: PrimitiveFloat>(x: T, y: T) -> T
1842where
1843    Float: From<T> + PartialOrd<T>,
1844    for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
1845{
1846    emulate_float_float_to_float_fn(Float::hypot_prec, x, y)
1847}