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}