Skip to main content

malachite_float/float/arithmetic/
tanh.rs

1// Copyright © 2026 Mikhail Hogrefe
2//
3// Uses code adopted from the GNU MPFR Library.
4//
5//      Copyright 2001-2026 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::cos::round_bracket;
17use crate::float::arithmetic::cosh::monotone_rational_via_floats;
18use crate::float::arithmetic::round_near_x::{float_round_near_x, small_input_shortcut};
19use crate::float::arithmetic::sin::{UNDERFLOW_EXPONENT, underflowed};
20use crate::float::arithmetic::sinh::sinh_bound;
21use crate::{Float, emulate_float_to_float_fn, emulate_rational_to_float_fn};
22use core::cmp::Ordering::{self, Equal};
23use core::cmp::{max, min};
24use malachite_base::num::arithmetic::traits::{
25    Abs, CeilingLogBase2, FloorLogBase2, PowerOf2, Square, Tanh, TanhAssign,
26};
27use malachite_base::num::basic::floats::PrimitiveFloat;
28use malachite_base::num::basic::integers::PrimitiveInt;
29use malachite_base::num::basic::traits::{
30    NaN as NaNTrait, NegativeOne, One, Two, Zero as ZeroTrait,
31};
32use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom};
33use malachite_base::num::logic::traits::SignificantBits;
34use malachite_base::rounding_modes::RoundingMode::{self, *};
35use malachite_nz::natural::Natural;
36use malachite_nz::natural::arithmetic::float::round::float_can_round;
37use malachite_nz::platform::Limb;
38use malachite_q::Rational;
39
40// A lower bound on 2|x| log_2(e) for a finite |x| = `x_abs`, used to bound exp(-2|x|) from above: f
41// + 7 floor(f / 16), where f = floor(2|x|), saturating. Since log_2(e) = 1.4426... > 1 + 7/16, this
42// is at most 2|x| (1 + 7/16) <= 2|x| log_2(e). An |x| of 2^62 or more gives far more bits than any
43// precision.
44pub(crate) fn two_x_log_2_e_lower_bound(x_abs: &Float) -> u64 {
45    let f = if x_abs.get_exponent().unwrap() > 62 {
46        u64::MAX
47    } else {
48        u64::rounding_from(&(x_abs << 1u32), Floor).0
49    };
50    f.saturating_add((f >> 4) * 7)
51}
52
53// Computes tanh(x) for a finite nonzero x with |x| = `x_abs` so large that tanh(x) is close to ±1:
54// MPFR's `set_one` label, which sets the result to ±1 or its neighbor toward zero. That is correct
55// only when 1 - tanh(|x|) is below half an ulp of the output, which MPFR takes for granted; here it
56// is checked, using 0 < 1 - tanh(|x|) = 2 / (exp(2|x|) + 1) < 2 exp(-2|x|) = 2^(1 - 2|x| log_2(e)),
57// and when it fails (at a precision beyond about 2.9|x| bits), the result is computed from expm1.
58fn tanh_near_one(x_abs: &Float, positive: bool, prec: u64, rm: RoundingMode) -> (Float, Ordering) {
59    // 1 - tanh(|x|) < 2^(1 - err)
60    let err = two_x_log_2_e_lower_bound(x_abs);
61    let one = if positive {
62        Float::ONE
63    } else {
64        Float::NEGATIVE_ONE
65    };
66    if err > prec + 1
67        && let Some(result) = float_round_near_x(&one, min(err, prec + 2), false, prec, rm)
68    {
69        return result;
70    }
71    tanh_via_exp_x_minus_1(x_abs, positive, prec, rm)
72}
73
74// Computes tanh(x) for a finite nonzero x with |x| = `x_abs` as -expm1(-2|x|) / (2 + expm1(-2|x|)),
75// signed. This form has no cancellation for a large |x|, where tanh(x) is close to ±1, and expm1
76// handles arguments so negative that exp(-2|x|) underflows. With e = expm1(-2|x|) rounded to
77// nearest, the numerator -e has a relative error below 2^-w, the denominator 2 + e, which exceeds 1
78// > |e|, one below 2 * 2^-w, and the division adds another 2^-w: in all, below 4 ulps.
79fn tanh_via_exp_x_minus_1(
80    x_abs: &Float,
81    positive: bool,
82    prec: u64,
83    rm: RoundingMode,
84) -> (Float, Ordering) {
85    let mut working_prec = prec + prec.ceiling_log_base_2() + 10;
86    let mut increment = Limb::WIDTH;
87    loop {
88        let e = (-(x_abs << 1u32)).exp_x_minus_1_prec(working_prec).0;
89        let denominator = &e + Float::TWO;
90        let t = -e / denominator;
91        if float_can_round(t.significand_ref().unwrap(), working_prec - 3, prec, rm) {
92            return Float::from_float_prec_round(if positive { t } else { -t }, prec, rm);
93        }
94        working_prec += increment;
95        increment = working_prec >> 1;
96    }
97}
98
99// This is mpfr_tanh from tanh.c, MPFR 4.2.2, where the input is finite and nonzero.
100fn tanh_prec_round_normal_ref(xt: &Float, prec: u64, rm: RoundingMode) -> (Float, Ordering) {
101    assert_ne!(rm, Exact, "Inexact tanh");
102    let exp_xt = i64::from(xt.get_exponent().unwrap());
103    // tanh(x) = x - x^3/3 + ... so the error is < 2^(3*EXP(x)-1)
104    //
105    // MPFR_FAST_COMPUTE_IF_SMALL_INPUT (y, xt, -2 * MPFR_GET_EXP (xt), 1, 0, rnd_mode, {});
106    if let Some(result) = small_input_shortcut(xt, -(exp_xt << 1), 1, false, prec, rm) {
107        return result;
108    }
109    let x = xt.abs();
110    let positive = xt.is_sign_positive();
111    // First check for BIG overflow of exp(2*x): For x > 0, exp(2*x) > 2^(2*x). If 2 ^(2*x) > 2^emax
112    // or x>emax/2, there is an overflow
113    if x >= const { Float::MAX_EXPONENT >> 1 } {
114        return tanh_near_one(&x, positive, prec, rm);
115    }
116    // The optimal number of bits: see algorithms.tex
117    let mut working_prec = prec + prec.ceiling_log_base_2() + 4;
118    // if x is small, there will be a cancellation in exp(2x)-1
119    if exp_xt < 0 {
120        working_prec += u64::exact_from(-exp_xt);
121    }
122    // The error analysis in algorithms.tex assumes that 2x is exact. MPFR raises its working
123    // precision to the precision of x to make it so, but in Malachite doubling a Float is always
124    // exact, so a precise input does not force a precise exponential.
125    let two_x = &x << 1u32;
126    let mut increment = Limb::WIDTH;
127    loop {
128        // tanh(x) = (exp(2x)-1)/(exp(2x)+1); since x > 0, exp(2x) can only overflow
129        let mut exp_2x = two_x.exp_prec_ref(working_prec).0;
130        if exp_2x.is_infinite() {
131            return tanh_near_one(&x, positive, prec, rm);
132        }
133        let exp_exp_2x = i64::from(exp_2x.get_exponent().unwrap());
134        let denominator = exp_2x.add_round_ref_val(Float::ONE, Floor).0;
135        exp_2x.sub_round_assign(Float::ONE, Ceiling);
136        // The subtraction cancels k = EXP(exp(2x)) - EXP(exp(2x) - 1) bits.
137        let k = exp_exp_2x - i64::from(exp_2x.get_exponent().unwrap());
138        let quotient = exp_2x / denominator;
139        // Calculation of the error, see algorithms.tex: below 2^max(3, k + 1) ulps, provided that
140        // max(3, k + 1) <= floor(p/2).
141        let d = max(3, k + 1);
142        let err = i64::exact_from(working_prec) - (d + 1);
143        if d <= i64::exact_from(working_prec >> 1)
144            && float_can_round(
145                quotient.significand_ref().unwrap(),
146                u64::exact_from(err),
147                prec,
148                rm,
149            )
150        {
151            return Float::from_float_prec_round(
152                if positive { quotient } else { -quotient },
153                prec,
154                rm,
155            );
156        }
157        // if the quotient is 1, tanh(x) is close to 1, being below it
158        if quotient.get_exponent() == Some(1) {
159            return tanh_near_one(&x, positive, prec, rm);
160        }
161        working_prec += increment;
162        increment = working_prec >> 1;
163    }
164}
165
166// A bound for cosh(t), for a nonzero `Rational` t with |t| < 1/2, from the partial sum C_k of its
167// series, 1 + t^2/2! + ... + t^(2k-2)/(2k-2)!, with k chosen from the bit length of t alone so that
168// the first omitted term t^(2k)/(2k)! is below 2^-(w+4). Every term is positive, so C_k is a lower
169// bound, and the remainder, less than twice the first omitted term, is below 2^-(w+3) <= C_k
170// 2^-(w+3), so C_k (1 + 2^-(w+3)) is an upper bound. As in `sinh_bound`, the scaling is a
171// multiplication and a shift, and for a tiny t, where one term suffices, t is not even squared.
172pub(crate) fn cosh_bound(t: &Rational, w: u64, upper: bool) -> Rational {
173    // |t| < 2^(log + 1), with log < 0
174    let log = t.floor_log_base_2_abs();
175    assert!(log < -1);
176    // |t|^(2k) / (2k)! < 2^(2k (log + 1) - log_factorial), where log_factorial <= log2((2k)!)
177    let mut k = 1u64;
178    let mut log_factorial = 1u64; // floor(log2(2))
179    let target = -i128::from(w) - 4;
180    while i128::from(k << 1) * i128::from(log + 1) - i128::from(log_factorial) > target {
181        k += 1;
182        let two_k = k << 1;
183        log_factorial += (two_k - 1).floor_log_base_2() + two_k.floor_log_base_2();
184    }
185    let mut c = Rational::ONE;
186    if k > 1 {
187        let t_squared = t.square();
188        let mut term = Rational::ONE;
189        for j in 1..k {
190            term *= &t_squared;
191            term /= Rational::from(((j << 1) - 1) * (j << 1));
192            c += &term;
193        }
194    }
195    if upper {
196        let shift = w + 3;
197        c *= Rational::from(Natural::power_of_2(shift) + Natural::ONE);
198        c >>= shift;
199    }
200    c
201}
202
203// Brackets tanh(x) = sinh(x) / cosh(x) for a nonzero `Rational` x, small enough that the series of
204// both converge in a few terms, by bounds on the two, tightening the bracket until both ends round
205// the same way. This also covers inputs so small that their hyperbolic tangents underflow, since
206// everything is done in `Rational` arithmetic.
207fn tanh_rational_series(x: &Rational, prec: u64, rm: RoundingMode) -> (Float, Ordering) {
208    let mut w = prec + 10;
209    let mut increment = Limb::WIDTH;
210    loop {
211        // |tanh(x)| lies strictly between |sinh| bounded toward zero over cosh bounded above, and
212        // |sinh| bounded away from zero over cosh bounded below.
213        let toward_zero = sinh_bound(x, w, false) / cosh_bound(x, w, true);
214        let away_from_zero = sinh_bound(x, w, true) / cosh_bound(x, w, false);
215        let (lo, hi) = if *x > 0u32 {
216            (toward_zero, away_from_zero)
217        } else {
218            (away_from_zero, toward_zero)
219        };
220        if let Some(result) = round_bracket(&lo, &hi, prec, rm) {
221            return result;
222        }
223        w += increment;
224        increment = w >> 1;
225    }
226}
227
228// Computes tanh(x) for a nonzero `Rational` x, rounded to precision `prec` with rounding mode `rm`.
229// tanh(x) is transcendental for every nonzero rational x, so the result is never exact.
230fn tanh_rational_helper(x: &Rational, prec: u64, rm: RoundingMode) -> (Float, Ordering) {
231    assert_ne!(rm, Exact, "Inexact tanh");
232    let positive = *x > 0u32;
233    let exp_x = x.floor_log_base_2_abs() + 1; // the MPFR-style exponent of x
234    if exp_x < UNDERFLOW_EXPONENT {
235        // |tanh(x)| < |x| < 2^(MIN_EXPONENT - 2), half the smallest positive Float, so the result
236        // is zero or that Float, by the rounding mode alone, with no 2^30-bit arithmetic needed.
237        return underflowed(positive, prec, rm);
238    }
239    // As for `sinh`, a small x is handled by series. This also covers every remaining x too small
240    // to be a `Float`.
241    if exp_x < -1 && u64::exact_from(-exp_x) << 4 >= prec + 10 {
242        return tanh_rational_series(x, prec, rm);
243    }
244    // |x| >= 2^(MAX_EXPONENT - 1), so 0 < 1 - |tanh(x)| < 2^(1 - 2|x|) is far below half an ulp of
245    // 1 at any precision, and the result rounds from ±1.
246    if exp_x >= Float::MAX_EXPONENT_I64 {
247        let one = if positive {
248            Float::ONE
249        } else {
250            Float::NEGATIVE_ONE
251        };
252        return float_round_near_x(&one, prec + 2, false, prec, rm).unwrap();
253    }
254    // tanh is increasing, so bracket x between the Floats x_lo <= x <= x_hi, take the hyperbolic
255    // tangent of both, and increase the working precision until the two round to the same result,
256    // which the exact tanh(x), lying between them, must then share.
257    monotone_rational_via_floats(x, prec, rm, tanh_prec_round_normal_ref)
258}
259
260impl Float {
261    /// Computes $\tanh x$, the hyperbolic tangent of a [`Float`], rounding the result to the
262    /// specified precision and with the specified rounding mode. The [`Float`] is taken by value.
263    /// An [`Ordering`] is also returned, indicating whether the rounded hyperbolic tangent is less
264    /// than, equal to, or greater than the exact hyperbolic tangent. Although `NaN`s are not
265    /// comparable to any [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
266    ///
267    /// See [`RoundingMode`] for a description of the possible rounding modes.
268    ///
269    /// $$
270    /// f(x,p,m) = \tanh x+\varepsilon.
271    /// $$
272    /// - If $\tanh x$ is zero or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
273    /// - If $\tanh x$ is finite, nonzero, and nonzero, and $m$ is not `Nearest`, then
274    ///   $|\varepsilon| < 2^{\lfloor\log_2 \tanh x\rfloor-p+1}$.
275    /// - If $\tanh x$ is finite, nonzero, and nonzero, and $m$ is `Nearest`, then $|\varepsilon|
276    ///   \leq 2^{\lfloor\log_2 \tanh x\rfloor-p}$.
277    ///
278    /// If the output has a precision, it is `prec`.
279    ///
280    /// Special cases:
281    /// - $f(\text{NaN},p,m)=\text{NaN}$
282    /// - $f(\infty,p,m)=1.0$
283    /// - $f(-\infty,p,m)=-1.0$
284    /// - $f(0.0,p,m)=0.0$
285    /// - $f(-0.0,p,m)=-0.0$
286    ///
287    /// Overflow and underflow:
288    /// - Since $|\tanh x|<1$, the result never overflows.
289    /// - If $0<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
290    /// - If $0<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
291    ///   instead.
292    /// - If $0<f(x,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
293    /// - If $2^{-2^{30}-1}<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
294    ///   instead.
295    /// - If $-2^{-2^{30}}<f(x,p,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned instead.
296    /// - If $-2^{-2^{30}}<f(x,p,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
297    ///   instead.
298    /// - If $-2^{-2^{30}-1}\leq f(x,p,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
299    /// - If $-2^{-2^{30}}<f(x,p,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
300    ///   returned instead.
301    ///
302    /// Since $|\tanh x|<|x|$, underflow requires an input of magnitude $2^{-2^{30}}$, the smallest
303    /// positive [`Float`], rounded toward zero.
304    ///
305    /// If you know you'll be using `Nearest`, consider using [`Float::tanh_prec`] instead. If you
306    /// know that your target precision is the precision of the input, consider using
307    /// [`Float::tanh_round`] instead. If both of these things are true, consider using
308    /// [`Float::tanh`] instead.
309    ///
310    /// # Worst-case complexity
311    /// $T(n, m) = O((n+m)^{3/2} \log (n+m) \log\log (n+m))$
312    ///
313    /// $M(n, m) = O((n+m) \log (n+m))$
314    ///
315    /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
316    /// `self.significant_bits()`: the exponential is computed at a working precision of `prec` plus
317    /// the bits lost to cancellation for a small input, which is at most about half the input's
318    /// precision when the small-input shortcut does not apply.
319    ///
320    /// # Panics
321    /// Panics if `rm` is `Exact` and `self` is finite and nonzero, since the hyperbolic tangent of
322    /// a finite nonzero [`Float`] is never exactly representable, or if `prec` is zero.
323    ///
324    /// # Examples
325    /// ```
326    /// use malachite_base::rounding_modes::RoundingMode::*;
327    /// use malachite_float::Float;
328    /// use std::cmp::Ordering::*;
329    ///
330    /// let (c, o) = Float::from_unsigned_prec(1u32, 100)
331    ///     .0
332    ///     .tanh_prec_round(5, Floor);
333    /// assert_eq!(c.to_string(), "0.750");
334    /// assert_eq!(o, Less);
335    ///
336    /// let (c, o) = Float::from_unsigned_prec(1u32, 100)
337    ///     .0
338    ///     .tanh_prec_round(5, Ceiling);
339    /// assert_eq!(c.to_string(), "0.781");
340    /// assert_eq!(o, Greater);
341    ///
342    /// let (c, o) = Float::from_unsigned_prec(1u32, 100)
343    ///     .0
344    ///     .tanh_prec_round(5, Nearest);
345    /// assert_eq!(c.to_string(), "0.750");
346    /// assert_eq!(o, Less);
347    ///
348    /// let (c, o) = Float::from_unsigned_prec(1u32, 100)
349    ///     .0
350    ///     .tanh_prec_round(20, Floor);
351    /// assert_eq!(c.to_string(), "0.76159382");
352    /// assert_eq!(o, Less);
353    ///
354    /// let (c, o) = Float::from_unsigned_prec(1u32, 100)
355    ///     .0
356    ///     .tanh_prec_round(20, Ceiling);
357    /// assert_eq!(c.to_string(), "0.76159477");
358    /// assert_eq!(o, Greater);
359    ///
360    /// let (c, o) = Float::from_unsigned_prec(1u32, 100)
361    ///     .0
362    ///     .tanh_prec_round(20, Nearest);
363    /// assert_eq!(c.to_string(), "0.76159382");
364    /// assert_eq!(o, Less);
365    /// ```
366    #[inline]
367    pub fn tanh_prec_round(self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
368        self.tanh_prec_round_ref(prec, rm)
369    }
370
371    /// Computes $\tanh x$, the hyperbolic tangent of a [`Float`], rounding the result to the
372    /// specified precision and with the specified rounding mode. The [`Float`] is taken by
373    /// reference. An [`Ordering`] is also returned, indicating whether the rounded hyperbolic
374    /// cosine is less than, equal to, or greater than the exact hyperbolic tangent. Although `NaN`s
375    /// are not comparable to any [`Float`], whenever this function returns a `NaN` it also returns
376    /// `Equal`.
377    ///
378    /// See [`RoundingMode`] for a description of the possible rounding modes.
379    ///
380    /// $$
381    /// f(x,p,m) = \tanh x+\varepsilon.
382    /// $$
383    /// - If $\tanh x$ is zero or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
384    /// - If $\tanh x$ is finite, nonzero, and nonzero, and $m$ is not `Nearest`, then
385    ///   $|\varepsilon| < 2^{\lfloor\log_2 \tanh x\rfloor-p+1}$.
386    /// - If $\tanh x$ is finite, nonzero, and nonzero, and $m$ is `Nearest`, then $|\varepsilon|
387    ///   \leq 2^{\lfloor\log_2 \tanh x\rfloor-p}$.
388    ///
389    /// If the output has a precision, it is `prec`.
390    ///
391    /// Special cases:
392    /// - $f(\text{NaN},p,m)=\text{NaN}$
393    /// - $f(\infty,p,m)=1.0$
394    /// - $f(-\infty,p,m)=-1.0$
395    /// - $f(0.0,p,m)=0.0$
396    /// - $f(-0.0,p,m)=-0.0$
397    ///
398    /// Overflow and underflow:
399    /// - Since $|\tanh x|<1$, the result never overflows.
400    /// - If $0<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
401    /// - If $0<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
402    ///   instead.
403    /// - If $0<f(x,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
404    /// - If $2^{-2^{30}-1}<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
405    ///   instead.
406    /// - If $-2^{-2^{30}}<f(x,p,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned instead.
407    /// - If $-2^{-2^{30}}<f(x,p,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
408    ///   instead.
409    /// - If $-2^{-2^{30}-1}\leq f(x,p,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
410    /// - If $-2^{-2^{30}}<f(x,p,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
411    ///   returned instead.
412    ///
413    /// Since $|\tanh x|<|x|$, underflow requires an input of magnitude $2^{-2^{30}}$, the smallest
414    /// positive [`Float`], rounded toward zero.
415    ///
416    /// If you know you'll be using `Nearest`, consider using [`Float::tanh_prec_ref`] instead. If
417    /// you know that your target precision is the precision of the input, consider using
418    /// [`Float::tanh_round_ref`] instead. If both of these things are true, consider using
419    /// `(&Float).tanh()` instead.
420    ///
421    /// # Worst-case complexity
422    /// $T(n, m) = O((n+m)^{3/2} \log (n+m) \log\log (n+m))$
423    ///
424    /// $M(n, m) = O((n+m) \log (n+m))$
425    ///
426    /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
427    /// `self.significant_bits()`: the exponential is computed at a working precision of `prec` plus
428    /// the bits lost to cancellation for a small input, which is at most about half the input's
429    /// precision when the small-input shortcut does not apply.
430    ///
431    /// # Panics
432    /// Panics if `rm` is `Exact` and `self` is finite and nonzero, since the hyperbolic tangent of
433    /// a finite nonzero [`Float`] is never exactly representable, or if `prec` is zero.
434    ///
435    /// # Examples
436    /// ```
437    /// use malachite_base::rounding_modes::RoundingMode::*;
438    /// use malachite_float::Float;
439    /// use std::cmp::Ordering::*;
440    ///
441    /// let (c, o) = Float::from_unsigned_prec(1u32, 100)
442    ///     .0
443    ///     .tanh_prec_round_ref(5, Floor);
444    /// assert_eq!(c.to_string(), "0.750");
445    /// assert_eq!(o, Less);
446    ///
447    /// let (c, o) = Float::from_unsigned_prec(1u32, 100)
448    ///     .0
449    ///     .tanh_prec_round_ref(5, Ceiling);
450    /// assert_eq!(c.to_string(), "0.781");
451    /// assert_eq!(o, Greater);
452    ///
453    /// let (c, o) = Float::from_unsigned_prec(1u32, 100)
454    ///     .0
455    ///     .tanh_prec_round_ref(5, Nearest);
456    /// assert_eq!(c.to_string(), "0.750");
457    /// assert_eq!(o, Less);
458    ///
459    /// let (c, o) = Float::from_unsigned_prec(1u32, 100)
460    ///     .0
461    ///     .tanh_prec_round_ref(20, Floor);
462    /// assert_eq!(c.to_string(), "0.76159382");
463    /// assert_eq!(o, Less);
464    ///
465    /// let (c, o) = Float::from_unsigned_prec(1u32, 100)
466    ///     .0
467    ///     .tanh_prec_round_ref(20, Ceiling);
468    /// assert_eq!(c.to_string(), "0.76159477");
469    /// assert_eq!(o, Greater);
470    ///
471    /// let (c, o) = Float::from_unsigned_prec(1u32, 100)
472    ///     .0
473    ///     .tanh_prec_round_ref(20, Nearest);
474    /// assert_eq!(c.to_string(), "0.76159382");
475    /// assert_eq!(o, Less);
476    /// ```
477    pub fn tanh_prec_round_ref(&self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
478        assert_ne!(prec, 0);
479        match &self.0 {
480            NaN => (Self::NAN, Equal),
481            // tanh(inf) = 1 && tanh(-inf) = -1
482            Infinity { sign } => (
483                if *sign {
484                    Self::one_prec(prec)
485                } else {
486                    -Self::one_prec(prec)
487                },
488                Equal,
489            ),
490            // tanh (0) = 0
491            Zero { .. } => (self.clone(), Equal),
492            Finite { .. } => tanh_prec_round_normal_ref(self, prec, rm),
493        }
494    }
495
496    /// Computes $\tanh x$, the hyperbolic tangent of a [`Float`], rounding the result to the
497    /// nearest value of the specified precision. The [`Float`] is taken by value. An [`Ordering`]
498    /// is also returned, indicating whether the rounded hyperbolic tangent is less than, equal to,
499    /// or greater than the exact hyperbolic tangent. Although `NaN`s are not comparable to any
500    /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
501    ///
502    /// If the hyperbolic tangent is equidistant from two [`Float`]s with the specified precision,
503    /// the [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
504    /// description of the `Nearest` rounding mode.
505    ///
506    /// $$
507    /// f(x,p) = \tanh x+\varepsilon.
508    /// $$
509    /// - If $\tanh x$ is zero or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
510    /// - If $\tanh x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |\tanh
511    ///   x|\rfloor-p}$.
512    ///
513    /// If the output has a precision, it is `prec`.
514    ///
515    /// Special cases:
516    /// - $f(\text{NaN},p)=\text{NaN}$
517    /// - $f(\infty,p)=1.0$
518    /// - $f(-\infty,p)=-1.0$
519    /// - $f(0.0,p)=0.0$
520    /// - $f(-0.0,p)=-0.0$
521    ///
522    /// Overflow and underflow:
523    /// - Since $|\tanh x|<1$, the result never overflows.
524    /// - If $0<f(x,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
525    /// - If $2^{-2^{30}-1}<f(x,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
526    /// - If $-2^{-2^{30}-1}\leq f(x,p)<0$, $-0.0$ is returned instead.
527    /// - If $-2^{-2^{30}}<f(x,p)<-2^{-2^{30}-1}$, $-2^{-2^{30}}$ is returned instead.
528    ///
529    /// If you want to use a rounding mode other than `Nearest`, consider using
530    /// [`Float::tanh_prec_round`] instead. If you know that your target precision is the precision
531    /// of the input, consider using [`Float::tanh`] instead.
532    ///
533    /// # Worst-case complexity
534    /// $T(n, m) = O((n+m)^{3/2} \log (n+m) \log\log (n+m))$
535    ///
536    /// $M(n, m) = O((n+m) \log (n+m))$
537    ///
538    /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
539    /// `self.significant_bits()`: the exponential is computed at a working precision of `prec` plus
540    /// the bits lost to cancellation for a small input, which is at most about half the input's
541    /// precision when the small-input shortcut does not apply.
542    ///
543    /// # Panics
544    /// Panics if `prec` is zero.
545    ///
546    /// # Examples
547    /// ```
548    /// use malachite_float::Float;
549    /// use std::cmp::Ordering::*;
550    ///
551    /// let (c, o) = Float::from_unsigned_prec(1u32, 100).0.tanh_prec(5);
552    /// assert_eq!(c.to_string(), "0.750");
553    /// assert_eq!(o, Less);
554    ///
555    /// let (c, o) = Float::from_unsigned_prec(1u32, 100).0.tanh_prec(20);
556    /// assert_eq!(c.to_string(), "0.76159382");
557    /// assert_eq!(o, Less);
558    /// ```
559    #[inline]
560    pub fn tanh_prec(self, prec: u64) -> (Self, Ordering) {
561        self.tanh_prec_round(prec, Nearest)
562    }
563
564    /// Computes $\tanh x$, the hyperbolic tangent of a [`Float`], rounding the result to the
565    /// nearest value of the specified precision. The [`Float`] is taken by reference. An
566    /// [`Ordering`] is also returned, indicating whether the rounded hyperbolic tangent is less
567    /// than, equal to, or greater than the exact hyperbolic tangent. Although `NaN`s are not
568    /// comparable to any [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
569    ///
570    /// If the hyperbolic tangent is equidistant from two [`Float`]s with the specified precision,
571    /// the [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
572    /// description of the `Nearest` rounding mode.
573    ///
574    /// $$
575    /// f(x,p) = \tanh x+\varepsilon.
576    /// $$
577    /// - If $\tanh x$ is zero or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
578    /// - If $\tanh x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |\tanh
579    ///   x|\rfloor-p}$.
580    ///
581    /// If the output has a precision, it is `prec`.
582    ///
583    /// Special cases:
584    /// - $f(\text{NaN},p)=\text{NaN}$
585    /// - $f(\infty,p)=1.0$
586    /// - $f(-\infty,p)=-1.0$
587    /// - $f(0.0,p)=0.0$
588    /// - $f(-0.0,p)=-0.0$
589    ///
590    /// Overflow and underflow:
591    /// - Since $|\tanh x|<1$, the result never overflows.
592    /// - If $0<f(x,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
593    /// - If $2^{-2^{30}-1}<f(x,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
594    /// - If $-2^{-2^{30}-1}\leq f(x,p)<0$, $-0.0$ is returned instead.
595    /// - If $-2^{-2^{30}}<f(x,p)<-2^{-2^{30}-1}$, $-2^{-2^{30}}$ is returned instead.
596    ///
597    /// If you want to use a rounding mode other than `Nearest`, consider using
598    /// [`Float::tanh_prec_round_ref`] instead. If you know that your target precision is the
599    /// precision of the input, consider using `(&Float).tanh()` instead.
600    ///
601    /// # Worst-case complexity
602    /// $T(n, m) = O((n+m)^{3/2} \log (n+m) \log\log (n+m))$
603    ///
604    /// $M(n, m) = O((n+m) \log (n+m))$
605    ///
606    /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
607    /// `self.significant_bits()`: the exponential is computed at a working precision of `prec` plus
608    /// the bits lost to cancellation for a small input, which is at most about half the input's
609    /// precision when the small-input shortcut does not apply.
610    ///
611    /// # Panics
612    /// Panics if `prec` is zero.
613    ///
614    /// # Examples
615    /// ```
616    /// use malachite_float::Float;
617    /// use std::cmp::Ordering::*;
618    ///
619    /// let (c, o) = Float::from_unsigned_prec(1u32, 100).0.tanh_prec_ref(5);
620    /// assert_eq!(c.to_string(), "0.750");
621    /// assert_eq!(o, Less);
622    ///
623    /// let (c, o) = Float::from_unsigned_prec(1u32, 100).0.tanh_prec_ref(20);
624    /// assert_eq!(c.to_string(), "0.76159382");
625    /// assert_eq!(o, Less);
626    /// ```
627    #[inline]
628    pub fn tanh_prec_ref(&self, prec: u64) -> (Self, Ordering) {
629        self.tanh_prec_round_ref(prec, Nearest)
630    }
631
632    /// Computes $\tanh x$, the hyperbolic tangent of a [`Float`], rounding the result with the
633    /// specified rounding mode. The [`Float`] is taken by value. An [`Ordering`] is also returned,
634    /// indicating whether the rounded hyperbolic tangent is less than, equal to, or greater than
635    /// the exact hyperbolic tangent. Although `NaN`s are not comparable to any [`Float`], whenever
636    /// this function returns a `NaN` it also returns `Equal`.
637    ///
638    /// The precision of the output is the precision of the input. See [`RoundingMode`] for a
639    /// description of the possible rounding modes.
640    ///
641    /// $$
642    /// f(x,m) = \tanh x+\varepsilon.
643    /// $$
644    /// - If $\tanh x$ is zero or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
645    /// - If $\tanh x$ is finite, nonzero, and nonzero, and $m$ is not `Nearest`, then
646    ///   $|\varepsilon| < 2^{\lfloor\log_2 \tanh x\rfloor-p+1}$, where $p$ is the precision of the
647    ///   input.
648    /// - If $\tanh x$ is finite, nonzero, and nonzero, and $m$ is `Nearest`, then $|\varepsilon|
649    ///   \leq 2^{\lfloor\log_2 \tanh x\rfloor-p}$, where $p$ is the precision of the input.
650    ///
651    /// If the output has a precision, it is the precision of the input.
652    ///
653    /// Special cases:
654    /// - $f(\text{NaN},m)=\text{NaN}$
655    /// - $f(\infty,m)=1.0$
656    /// - $f(-\infty,m)=-1.0$
657    /// - $f(0.0,m)=0.0$
658    /// - $f(-0.0,m)=-0.0$
659    ///
660    /// See the [`Float::tanh_prec_round`] documentation for information on overflow and underflow.
661    ///
662    /// If you want to specify an output precision, consider using [`Float::tanh_prec_round`]
663    /// instead. If you know you'll be using the `Nearest` rounding mode, consider using
664    /// [`Float::tanh`] instead.
665    ///
666    /// # Worst-case complexity
667    /// $T(n) = O(n^{3/2} \log n \log\log n)$
668    ///
669    /// $M(n) = O(n \log n)$
670    ///
671    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
672    ///
673    /// # Panics
674    /// Panics if `rm` is `Exact` and `self` is finite and nonzero, since the hyperbolic tangent of
675    /// a finite nonzero [`Float`] is never exactly representable.
676    ///
677    /// # Examples
678    /// ```
679    /// use malachite_base::rounding_modes::RoundingMode::*;
680    /// use malachite_float::Float;
681    /// use std::cmp::Ordering::*;
682    ///
683    /// let (c, o) = Float::from_unsigned_prec(1u32, 100).0.tanh_round(Floor);
684    /// assert_eq!(c.to_string(), "0.76159415595576488811945828260469");
685    /// assert_eq!(o, Less);
686    ///
687    /// let (c, o) = Float::from_unsigned_prec(1u32, 100).0.tanh_round(Ceiling);
688    /// assert_eq!(c.to_string(), "0.76159415595576488811945828260548");
689    /// assert_eq!(o, Greater);
690    ///
691    /// let (c, o) = Float::from_unsigned_prec(1u32, 100).0.tanh_round(Nearest);
692    /// assert_eq!(c.to_string(), "0.76159415595576488811945828260469");
693    /// assert_eq!(o, Less);
694    /// ```
695    #[inline]
696    pub fn tanh_round(self, rm: RoundingMode) -> (Self, Ordering) {
697        let prec = self.significant_bits();
698        self.tanh_prec_round(prec, rm)
699    }
700
701    /// Computes $\tanh x$, the hyperbolic tangent of a [`Float`], rounding the result with the
702    /// specified rounding mode. The [`Float`] is taken by reference. An [`Ordering`] is also
703    /// returned, indicating whether the rounded hyperbolic tangent is less than, equal to, or
704    /// greater than the exact hyperbolic tangent. Although `NaN`s are not comparable to any
705    /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
706    ///
707    /// The precision of the output is the precision of the input. See [`RoundingMode`] for a
708    /// description of the possible rounding modes.
709    ///
710    /// $$
711    /// f(x,m) = \tanh x+\varepsilon.
712    /// $$
713    /// - If $\tanh x$ is zero or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
714    /// - If $\tanh x$ is finite, nonzero, and nonzero, and $m$ is not `Nearest`, then
715    ///   $|\varepsilon| < 2^{\lfloor\log_2 \tanh x\rfloor-p+1}$, where $p$ is the precision of the
716    ///   input.
717    /// - If $\tanh x$ is finite, nonzero, and nonzero, and $m$ is `Nearest`, then $|\varepsilon|
718    ///   \leq 2^{\lfloor\log_2 \tanh x\rfloor-p}$, where $p$ is the precision of the input.
719    ///
720    /// If the output has a precision, it is the precision of the input.
721    ///
722    /// Special cases:
723    /// - $f(\text{NaN},m)=\text{NaN}$
724    /// - $f(\infty,m)=1.0$
725    /// - $f(-\infty,m)=-1.0$
726    /// - $f(0.0,m)=0.0$
727    /// - $f(-0.0,m)=-0.0$
728    ///
729    /// See the [`Float::tanh_prec_round`] documentation for information on overflow and underflow.
730    ///
731    /// If you want to specify an output precision, consider using [`Float::tanh_prec_round_ref`]
732    /// instead. If you know you'll be using the `Nearest` rounding mode, consider using
733    /// `(&Float).tanh()` instead.
734    ///
735    /// # Worst-case complexity
736    /// $T(n) = O(n^{3/2} \log n \log\log n)$
737    ///
738    /// $M(n) = O(n \log n)$
739    ///
740    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
741    ///
742    /// # Panics
743    /// Panics if `rm` is `Exact` and `self` is finite and nonzero, since the hyperbolic tangent of
744    /// a finite nonzero [`Float`] is never exactly representable.
745    ///
746    /// # Examples
747    /// ```
748    /// use malachite_base::rounding_modes::RoundingMode::*;
749    /// use malachite_float::Float;
750    /// use std::cmp::Ordering::*;
751    ///
752    /// let (c, o) = Float::from_unsigned_prec(1u32, 100).0.tanh_round_ref(Floor);
753    /// assert_eq!(c.to_string(), "0.76159415595576488811945828260469");
754    /// assert_eq!(o, Less);
755    ///
756    /// let (c, o) = Float::from_unsigned_prec(1u32, 100)
757    ///     .0
758    ///     .tanh_round_ref(Ceiling);
759    /// assert_eq!(c.to_string(), "0.76159415595576488811945828260548");
760    /// assert_eq!(o, Greater);
761    ///
762    /// let (c, o) = Float::from_unsigned_prec(1u32, 100)
763    ///     .0
764    ///     .tanh_round_ref(Nearest);
765    /// assert_eq!(c.to_string(), "0.76159415595576488811945828260469");
766    /// assert_eq!(o, Less);
767    /// ```
768    #[inline]
769    pub fn tanh_round_ref(&self, rm: RoundingMode) -> (Self, Ordering) {
770        self.tanh_prec_round_ref(self.significant_bits(), rm)
771    }
772
773    /// Computes $\tanh x$, the hyperbolic tangent of a [`Float`], in place, rounding the result to
774    /// the specified precision and with the specified rounding mode. An [`Ordering`] is returned,
775    /// indicating whether the rounded hyperbolic tangent is less than, equal to, or greater than
776    /// the exact hyperbolic tangent. Although `NaN`s are not comparable to any [`Float`], whenever
777    /// this function sets the [`Float`] to `NaN` it also returns `Equal`.
778    ///
779    /// See [`RoundingMode`] for a description of the possible rounding modes.
780    ///
781    /// $$
782    /// x \gets \tanh x+\varepsilon.
783    /// $$
784    /// - If $\tanh x$ is zero or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
785    /// - If $\tanh x$ is finite, nonzero, and nonzero, and $m$ is not `Nearest`, then
786    ///   $|\varepsilon| < 2^{\lfloor\log_2 \tanh x\rfloor-p+1}$.
787    /// - If $\tanh x$ is finite, nonzero, and nonzero, and $m$ is `Nearest`, then $|\varepsilon|
788    ///   \leq 2^{\lfloor\log_2 \tanh x\rfloor-p}$.
789    ///
790    /// If the output has a precision, it is `prec`.
791    ///
792    /// See the [`Float::tanh_prec_round`] documentation for information on special cases and
793    /// overflow.
794    ///
795    /// If you know you'll be using `Nearest`, consider using [`Float::tanh_prec_assign`] instead.
796    /// If you know that your target precision is the precision of the input, consider using
797    /// [`Float::tanh_round_assign`] instead. If both of these things are true, consider using
798    /// [`Float::tanh_assign`] instead.
799    ///
800    /// # Worst-case complexity
801    /// $T(n, m) = O((n+m)^{3/2} \log (n+m) \log\log (n+m))$
802    ///
803    /// $M(n, m) = O((n+m) \log (n+m))$
804    ///
805    /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
806    /// `self.significant_bits()`: the exponential is computed at a working precision of `prec` plus
807    /// the bits lost to cancellation for a small input, which is at most about half the input's
808    /// precision when the small-input shortcut does not apply.
809    ///
810    /// # Panics
811    /// Panics if `rm` is `Exact` and `self` is finite and nonzero, since the hyperbolic tangent of
812    /// a finite nonzero [`Float`] is never exactly representable, or if `prec` is zero.
813    ///
814    /// # Examples
815    /// ```
816    /// use malachite_base::rounding_modes::RoundingMode::*;
817    /// use malachite_float::Float;
818    /// use std::cmp::Ordering::*;
819    ///
820    /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
821    /// assert_eq!(x.tanh_prec_round_assign(5, Floor), Less);
822    /// assert_eq!(x.to_string(), "0.750");
823    ///
824    /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
825    /// assert_eq!(x.tanh_prec_round_assign(5, Ceiling), Greater);
826    /// assert_eq!(x.to_string(), "0.781");
827    ///
828    /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
829    /// assert_eq!(x.tanh_prec_round_assign(5, Nearest), Less);
830    /// assert_eq!(x.to_string(), "0.750");
831    ///
832    /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
833    /// assert_eq!(x.tanh_prec_round_assign(20, Floor), Less);
834    /// assert_eq!(x.to_string(), "0.76159382");
835    ///
836    /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
837    /// assert_eq!(x.tanh_prec_round_assign(20, Ceiling), Greater);
838    /// assert_eq!(x.to_string(), "0.76159477");
839    ///
840    /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
841    /// assert_eq!(x.tanh_prec_round_assign(20, Nearest), Less);
842    /// assert_eq!(x.to_string(), "0.76159382");
843    /// ```
844    #[inline]
845    pub fn tanh_prec_round_assign(&mut self, prec: u64, rm: RoundingMode) -> Ordering {
846        let o;
847        (*self, o) = self.tanh_prec_round_ref(prec, rm);
848        o
849    }
850
851    /// Computes $\tanh x$, the hyperbolic tangent of a [`Float`], in place, rounding the result to
852    /// the nearest value of the specified precision. An [`Ordering`] is returned, indicating
853    /// whether the rounded hyperbolic tangent is less than, equal to, or greater than the exact
854    /// hyperbolic sine. Although `NaN`s are not comparable to any [`Float`], whenever this function
855    /// sets the [`Float`] to `NaN` it also returns `Equal`.
856    ///
857    /// If the hyperbolic tangent is equidistant from two [`Float`]s with the specified precision,
858    /// the [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
859    /// description of the `Nearest` rounding mode.
860    ///
861    /// $$
862    /// x \gets \tanh x+\varepsilon.
863    /// $$
864    /// - If $\tanh x$ is zero or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
865    /// - If $\tanh x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |\tanh
866    ///   x|\rfloor-p}$.
867    ///
868    /// If the output has a precision, it is `prec`.
869    ///
870    /// See the [`Float::tanh_prec`] documentation for information on special cases, overflow, and
871    /// underflow.
872    ///
873    /// If you want to use a rounding mode other than `Nearest`, consider using
874    /// [`Float::tanh_prec_round_assign`] instead. If you know that your target precision is the
875    /// precision of the input, consider using [`Float::tanh_assign`] instead.
876    ///
877    /// # Worst-case complexity
878    /// $T(n, m) = O((n+m)^{3/2} \log (n+m) \log\log (n+m))$
879    ///
880    /// $M(n, m) = O((n+m) \log (n+m))$
881    ///
882    /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
883    /// `self.significant_bits()`: the exponential is computed at a working precision of `prec` plus
884    /// the bits lost to cancellation for a small input, which is at most about half the input's
885    /// precision when the small-input shortcut does not apply.
886    ///
887    /// # Panics
888    /// Panics if `prec` is zero.
889    ///
890    /// # Examples
891    /// ```
892    /// use malachite_float::Float;
893    /// use std::cmp::Ordering::*;
894    ///
895    /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
896    /// assert_eq!(x.tanh_prec_assign(5), Less);
897    /// assert_eq!(x.to_string(), "0.750");
898    ///
899    /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
900    /// assert_eq!(x.tanh_prec_assign(20), Less);
901    /// assert_eq!(x.to_string(), "0.76159382");
902    /// ```
903    #[inline]
904    pub fn tanh_prec_assign(&mut self, prec: u64) -> Ordering {
905        self.tanh_prec_round_assign(prec, Nearest)
906    }
907
908    /// Computes $\tanh x$, the hyperbolic tangent of a [`Float`], in place, rounding the result
909    /// with the specified rounding mode. An [`Ordering`] is returned, indicating whether the
910    /// rounded hyperbolic tangent is less than, equal to, or greater than the exact hyperbolic
911    /// tangent. Although `NaN`s are not comparable to any [`Float`], whenever this function sets
912    /// the [`Float`] to `NaN` it also returns `Equal`.
913    ///
914    /// The precision of the output is the precision of the input. See [`RoundingMode`] for a
915    /// description of the possible rounding modes.
916    ///
917    /// $$
918    /// x \gets \tanh x+\varepsilon.
919    /// $$
920    /// - If $\tanh x$ is zero or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
921    /// - If $\tanh x$ is finite, nonzero, and nonzero, and $m$ is not `Nearest`, then
922    ///   $|\varepsilon| < 2^{\lfloor\log_2 \tanh x\rfloor-p+1}$, where $p$ is the precision of the
923    ///   input.
924    /// - If $\tanh x$ is finite, nonzero, and nonzero, and $m$ is `Nearest`, then $|\varepsilon|
925    ///   \leq 2^{\lfloor\log_2 \tanh x\rfloor-p}$, where $p$ is the precision of the input.
926    ///
927    /// If the output has a precision, it is the precision of the input.
928    ///
929    /// See the [`Float::tanh_round`] documentation for information on special cases, overflow, and
930    /// underflow.
931    ///
932    /// If you want to specify an output precision, consider using [`Float::tanh_prec_round_assign`]
933    /// instead. If you know you'll be using the `Nearest` rounding mode, consider using
934    /// [`Float::tanh_assign`] instead.
935    ///
936    /// # Worst-case complexity
937    /// $T(n) = O(n^{3/2} \log n \log\log n)$
938    ///
939    /// $M(n) = O(n \log n)$
940    ///
941    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
942    ///
943    /// # Panics
944    /// Panics if `rm` is `Exact` and `self` is finite and nonzero, since the hyperbolic tangent of
945    /// a finite nonzero [`Float`] is never exactly representable.
946    ///
947    /// # Examples
948    /// ```
949    /// use malachite_base::rounding_modes::RoundingMode::*;
950    /// use malachite_float::Float;
951    /// use std::cmp::Ordering::*;
952    ///
953    /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
954    /// assert_eq!(x.tanh_round_assign(Floor), Less);
955    /// assert_eq!(x.to_string(), "0.76159415595576488811945828260469");
956    ///
957    /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
958    /// assert_eq!(x.tanh_round_assign(Ceiling), Greater);
959    /// assert_eq!(x.to_string(), "0.76159415595576488811945828260548");
960    ///
961    /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
962    /// assert_eq!(x.tanh_round_assign(Nearest), Less);
963    /// assert_eq!(x.to_string(), "0.76159415595576488811945828260469");
964    /// ```
965    #[inline]
966    pub fn tanh_round_assign(&mut self, rm: RoundingMode) -> Ordering {
967        let prec = self.significant_bits();
968        self.tanh_prec_round_assign(prec, rm)
969    }
970}
971
972impl Float {
973    /// Computes $\tanh x$, the hyperbolic tangent of a [`Rational`], rounding the result to the
974    /// specified precision and with the specified rounding mode and returning the result as a
975    /// [`Float`]. The [`Rational`] is taken by value. An [`Ordering`] is also returned, indicating
976    /// whether the rounded hyperbolic tangent is less than, equal to, or greater than the exact
977    /// hyperbolic tangent.
978    ///
979    /// See [`RoundingMode`] for a description of the possible rounding modes.
980    ///
981    /// $$
982    /// f(x,p,m) = \tanh x+\varepsilon.
983    /// $$
984    /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{\lfloor\log_2 |\tanh x|\rfloor-p+1}$.
985    /// - If $m$ is `Nearest`, then $|\varepsilon| \leq 2^{\lfloor\log_2 |\tanh x|\rfloor-p}$.
986    ///
987    /// These bounds do not apply when the result underflows; see below.
988    ///
989    /// The output has precision `prec`.
990    ///
991    /// Special cases:
992    /// - $f(0,p,m)=0.0$.
993    ///
994    /// Overflow and underflow:
995    /// - Since $|\tanh x|<1$, the result never overflows.
996    /// - If $0<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
997    /// - If $0<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
998    ///   instead.
999    /// - If $0<f(x,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
1000    /// - If $2^{-2^{30}-1}<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
1001    ///   instead.
1002    /// - If $-2^{-2^{30}}<f(x,p,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned instead.
1003    /// - If $-2^{-2^{30}}<f(x,p,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
1004    ///   instead.
1005    /// - If $-2^{-2^{30}-1}\leq f(x,p,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
1006    /// - If $-2^{-2^{30}}<f(x,p,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
1007    ///   returned instead.
1008    ///
1009    /// Underflow requires an input of magnitude below about $2^{-2^{30}}$.
1010    ///
1011    /// If you know you'll be using `Nearest`, consider using [`Float::tanh_rational_prec`] instead.
1012    ///
1013    /// # Worst-case complexity
1014    /// $T(n, m) = O(n^{3/2} \log n \log\log n + m (\log m)^2 \log\log m)$
1015    ///
1016    /// $M(n, m) = O(n \log n + m \log m)$
1017    ///
1018    /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
1019    /// `x.significant_bits()`.
1020    ///
1021    /// # Panics
1022    /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
1023    /// with the given precision (which is the case for every nonzero input).
1024    ///
1025    /// # Examples
1026    /// ```
1027    /// use malachite_base::rounding_modes::RoundingMode::*;
1028    /// use malachite_float::Float;
1029    /// use malachite_q::Rational;
1030    /// use std::cmp::Ordering::*;
1031    ///
1032    /// let (t, o) = Float::tanh_rational_prec_round(Rational::from_unsigneds(3u8, 5), 5, Floor);
1033    /// assert_eq!(t.to_string(), "0.531");
1034    /// assert_eq!(o, Less);
1035    ///
1036    /// let (t, o) = Float::tanh_rational_prec_round(Rational::from_unsigneds(3u8, 5), 5, Ceiling);
1037    /// assert_eq!(t.to_string(), "0.562");
1038    /// assert_eq!(o, Greater);
1039    ///
1040    /// let (t, o) = Float::tanh_rational_prec_round(Rational::from_signeds(-3i8, 5), 20, Floor);
1041    /// assert_eq!(t.to_string(), "-0.53705025");
1042    /// assert_eq!(o, Less);
1043    ///
1044    /// let (t, o) = Float::tanh_rational_prec_round(Rational::from_signeds(-3i8, 5), 20, Ceiling);
1045    /// assert_eq!(t.to_string(), "-0.53704929");
1046    /// assert_eq!(o, Greater);
1047    /// ```
1048    #[allow(clippy::needless_pass_by_value)]
1049    #[inline]
1050    pub fn tanh_rational_prec_round(x: Rational, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
1051        Self::tanh_rational_prec_round_ref(&x, prec, rm)
1052    }
1053
1054    /// Computes $\tanh x$, the hyperbolic tangent of a [`Rational`], rounding the result to the
1055    /// specified precision and with the specified rounding mode and returning the result as a
1056    /// [`Float`]. The [`Rational`] is taken by reference. An [`Ordering`] is also returned,
1057    /// indicating whether the rounded hyperbolic tangent is less than, equal to, or greater than
1058    /// the exact hyperbolic tangent.
1059    ///
1060    /// See [`RoundingMode`] for a description of the possible rounding modes.
1061    ///
1062    /// $$
1063    /// f(x,p,m) = \tanh x+\varepsilon.
1064    /// $$
1065    /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{\lfloor\log_2 |\tanh x|\rfloor-p+1}$.
1066    /// - If $m$ is `Nearest`, then $|\varepsilon| \leq 2^{\lfloor\log_2 |\tanh x|\rfloor-p}$.
1067    ///
1068    /// These bounds do not apply when the result underflows; see below.
1069    ///
1070    /// The output has precision `prec`.
1071    ///
1072    /// Special cases:
1073    /// - $f(0,p,m)=0.0$.
1074    ///
1075    /// Overflow and underflow:
1076    /// - Since $|\tanh x|<1$, the result never overflows.
1077    /// - If $0<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
1078    /// - If $0<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
1079    ///   instead.
1080    /// - If $0<f(x,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
1081    /// - If $2^{-2^{30}-1}<f(x,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
1082    ///   instead.
1083    /// - If $-2^{-2^{30}}<f(x,p,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned instead.
1084    /// - If $-2^{-2^{30}}<f(x,p,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
1085    ///   instead.
1086    /// - If $-2^{-2^{30}-1}\leq f(x,p,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
1087    /// - If $-2^{-2^{30}}<f(x,p,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
1088    ///   returned instead.
1089    ///
1090    /// Underflow requires an input of magnitude below about $2^{-2^{30}}$.
1091    ///
1092    /// If you know you'll be using `Nearest`, consider using [`Float::tanh_rational_prec_ref`]
1093    /// instead.
1094    ///
1095    /// # Worst-case complexity
1096    /// $T(n, m) = O(n^{3/2} \log n \log\log n + m (\log m)^2 \log\log m)$
1097    ///
1098    /// $M(n, m) = O(n \log n + m \log m)$
1099    ///
1100    /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
1101    /// `x.significant_bits()`.
1102    ///
1103    /// # Panics
1104    /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
1105    /// with the given precision (which is the case for every nonzero input).
1106    ///
1107    /// # Examples
1108    /// ```
1109    /// use malachite_base::rounding_modes::RoundingMode::*;
1110    /// use malachite_float::Float;
1111    /// use malachite_q::Rational;
1112    /// use std::cmp::Ordering::*;
1113    ///
1114    /// let (t, o) =
1115    ///     Float::tanh_rational_prec_round_ref(&Rational::from_unsigneds(3u8, 5), 5, Floor);
1116    /// assert_eq!(t.to_string(), "0.531");
1117    /// assert_eq!(o, Less);
1118    ///
1119    /// let (t, o) =
1120    ///     Float::tanh_rational_prec_round_ref(&Rational::from_unsigneds(3u8, 5), 5, Ceiling);
1121    /// assert_eq!(t.to_string(), "0.562");
1122    /// assert_eq!(o, Greater);
1123    ///
1124    /// let (t, o) =
1125    ///     Float::tanh_rational_prec_round_ref(&Rational::from_signeds(-3i8, 5), 20, Floor);
1126    /// assert_eq!(t.to_string(), "-0.53705025");
1127    /// assert_eq!(o, Less);
1128    ///
1129    /// let (t, o) =
1130    ///     Float::tanh_rational_prec_round_ref(&Rational::from_signeds(-3i8, 5), 20, Ceiling);
1131    /// assert_eq!(t.to_string(), "-0.53704929");
1132    /// assert_eq!(o, Greater);
1133    /// ```
1134    pub fn tanh_rational_prec_round_ref(
1135        x: &Rational,
1136        prec: u64,
1137        rm: RoundingMode,
1138    ) -> (Self, Ordering) {
1139        assert_ne!(prec, 0);
1140        if *x == 0u32 {
1141            // tanh(0) = 0, exactly
1142            return (Self::ZERO, Equal);
1143        }
1144        tanh_rational_helper(x, prec, rm)
1145    }
1146
1147    /// Computes $\tanh x$, the hyperbolic tangent of a [`Rational`], rounding the result to the
1148    /// nearest value of the specified precision and returning the result as a [`Float`]. The
1149    /// [`Rational`] is taken by value. An [`Ordering`] is also returned, indicating whether the
1150    /// rounded hyperbolic tangent is less than, equal to, or greater than the exact hyperbolic
1151    /// tangent.
1152    ///
1153    /// If the hyperbolic tangent is equidistant from two [`Float`]s with the specified precision,
1154    /// the [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
1155    /// description of the `Nearest` rounding mode.
1156    ///
1157    /// $$
1158    /// f(x,p) = \tanh x+\varepsilon,
1159    /// $$
1160    /// where $|\varepsilon| \leq 2^{\lfloor\log_2 |\tanh x|\rfloor-p}$ (unless the result
1161    /// underflows; see below).
1162    ///
1163    /// The output has precision `prec`.
1164    ///
1165    /// Special cases:
1166    /// - $f(0,p)=0.0$.
1167    ///
1168    /// Overflow and underflow:
1169    /// - Since $|\tanh x|<1$, the result never overflows.
1170    /// - If $0<f(x,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
1171    /// - If $2^{-2^{30}-1}<f(x,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
1172    /// - If $-2^{-2^{30}-1}\leq f(x,p)<0$, $-0.0$ is returned instead.
1173    /// - If $-2^{-2^{30}}<f(x,p)<-2^{-2^{30}-1}$, $-2^{-2^{30}}$ is returned instead.
1174    ///
1175    /// If you want to use a rounding mode other than `Nearest`, consider using
1176    /// [`Float::tanh_rational_prec_round`] instead.
1177    ///
1178    /// # Worst-case complexity
1179    /// $T(n, m) = O(n^{3/2} \log n \log\log n + m (\log m)^2 \log\log m)$
1180    ///
1181    /// $M(n, m) = O(n \log n + m \log m)$
1182    ///
1183    /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
1184    /// `x.significant_bits()`.
1185    ///
1186    /// # Panics
1187    /// Panics if `prec` is zero.
1188    ///
1189    /// # Examples
1190    /// ```
1191    /// use malachite_base::num::basic::traits::Zero;
1192    /// use malachite_float::Float;
1193    /// use malachite_q::Rational;
1194    /// use std::cmp::Ordering::*;
1195    ///
1196    /// let (t, o) = Float::tanh_rational_prec(Rational::from_unsigneds(3u8, 5), 20);
1197    /// assert_eq!(t.to_string(), "0.53704929");
1198    /// assert_eq!(o, Less);
1199    ///
1200    /// let (t, o) = Float::tanh_rational_prec(Rational::ZERO, 10);
1201    /// assert_eq!(t.to_string(), "0.0");
1202    /// assert_eq!(o, Equal);
1203    /// ```
1204    #[allow(clippy::needless_pass_by_value)]
1205    #[inline]
1206    pub fn tanh_rational_prec(x: Rational, prec: u64) -> (Self, Ordering) {
1207        Self::tanh_rational_prec_round_ref(&x, prec, Nearest)
1208    }
1209
1210    /// Computes $\tanh x$, the hyperbolic tangent of a [`Rational`], rounding the result to the
1211    /// nearest value of the specified precision and returning the result as a [`Float`]. The
1212    /// [`Rational`] is taken by reference. An [`Ordering`] is also returned, indicating whether the
1213    /// rounded hyperbolic tangent is less than, equal to, or greater than the exact hyperbolic
1214    /// tangent.
1215    ///
1216    /// If the hyperbolic tangent is equidistant from two [`Float`]s with the specified precision,
1217    /// the [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
1218    /// description of the `Nearest` rounding mode.
1219    ///
1220    /// $$
1221    /// f(x,p) = \tanh x+\varepsilon,
1222    /// $$
1223    /// where $|\varepsilon| \leq 2^{\lfloor\log_2 |\tanh x|\rfloor-p}$ (unless the result
1224    /// underflows; see below).
1225    ///
1226    /// The output has precision `prec`.
1227    ///
1228    /// Special cases:
1229    /// - $f(0,p)=0.0$.
1230    ///
1231    /// Overflow and underflow:
1232    /// - Since $|\tanh x|<1$, the result never overflows.
1233    /// - If $0<f(x,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
1234    /// - If $2^{-2^{30}-1}<f(x,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
1235    /// - If $-2^{-2^{30}-1}\leq f(x,p)<0$, $-0.0$ is returned instead.
1236    /// - If $-2^{-2^{30}}<f(x,p)<-2^{-2^{30}-1}$, $-2^{-2^{30}}$ is returned instead.
1237    ///
1238    /// If you want to use a rounding mode other than `Nearest`, consider using
1239    /// [`Float::tanh_rational_prec_round_ref`] instead.
1240    ///
1241    /// # Worst-case complexity
1242    /// $T(n, m) = O(n^{3/2} \log n \log\log n + m (\log m)^2 \log\log m)$
1243    ///
1244    /// $M(n, m) = O(n \log n + m \log m)$
1245    ///
1246    /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
1247    /// `x.significant_bits()`.
1248    ///
1249    /// # Panics
1250    /// Panics if `prec` is zero.
1251    ///
1252    /// # Examples
1253    /// ```
1254    /// use malachite_base::num::basic::traits::Zero;
1255    /// use malachite_float::Float;
1256    /// use malachite_q::Rational;
1257    /// use std::cmp::Ordering::*;
1258    ///
1259    /// let (t, o) = Float::tanh_rational_prec_ref(&Rational::from_unsigneds(3u8, 5), 20);
1260    /// assert_eq!(t.to_string(), "0.53704929");
1261    /// assert_eq!(o, Less);
1262    ///
1263    /// let (t, o) = Float::tanh_rational_prec_ref(&Rational::ZERO, 10);
1264    /// assert_eq!(t.to_string(), "0.0");
1265    /// assert_eq!(o, Equal);
1266    /// ```
1267    #[inline]
1268    pub fn tanh_rational_prec_ref(x: &Rational, prec: u64) -> (Self, Ordering) {
1269        Self::tanh_rational_prec_round_ref(x, prec, Nearest)
1270    }
1271}
1272
1273impl Tanh for Float {
1274    type Output = Self;
1275
1276    /// Computes $\tanh x$, the hyperbolic tangent of a [`Float`], taking it by value.
1277    ///
1278    /// If the output has a precision, it is the precision of the input. If the hyperbolic tangent
1279    /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s
1280    /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
1281    /// rounding mode.
1282    ///
1283    /// $$
1284    /// f(x) = \tanh x+\varepsilon.
1285    /// $$
1286    /// - If $\tanh x$ is zero or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
1287    /// - If $\tanh x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |\tanh
1288    ///   x|\rfloor-p}$, where $p$ is the precision of the input.
1289    ///
1290    /// Special cases:
1291    /// - $f(\text{NaN})=\text{NaN}$
1292    /// - $f(\infty)=1.0$
1293    /// - $f(-\infty)=-1.0$
1294    /// - $f(0.0)=0.0$
1295    /// - $f(-0.0)=-0.0$
1296    ///
1297    /// See the [`Float::tanh_round`] documentation for information on overflow and underflow.
1298    ///
1299    /// If you want to use a rounding mode other than `Nearest`, consider using
1300    /// [`Float::tanh_round`] instead. If you want to specify the output precision, consider using
1301    /// [`Float::tanh_prec`]. If you want both of these things, consider using
1302    /// [`Float::tanh_prec_round`].
1303    ///
1304    /// # Worst-case complexity
1305    /// $T(n) = O(n^{3/2} \log n \log\log n)$
1306    ///
1307    /// $M(n) = O(n \log n)$
1308    ///
1309    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
1310    ///
1311    /// # Examples
1312    /// ```
1313    /// use malachite_base::num::arithmetic::traits::Tanh;
1314    /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity};
1315    /// use malachite_float::Float;
1316    ///
1317    /// assert!(Float::NAN.tanh().is_nan());
1318    /// assert_eq!(Float::INFINITY.tanh(), 1);
1319    /// assert_eq!(Float::NEGATIVE_INFINITY.tanh(), -1);
1320    /// assert_eq!(
1321    ///     Float::from_unsigned_prec(1u32, 100).0.tanh().to_string(),
1322    ///     "0.76159415595576488811945828260469"
1323    /// );
1324    /// ```
1325    #[inline]
1326    fn tanh(self) -> Self {
1327        let prec = self.significant_bits();
1328        self.tanh_prec_round(prec, Nearest).0
1329    }
1330}
1331
1332impl Tanh for &Float {
1333    type Output = Float;
1334
1335    /// Computes $\tanh x$, the hyperbolic tangent of a [`Float`], taking it by reference.
1336    ///
1337    /// If the output has a precision, it is the precision of the input. If the hyperbolic tangent
1338    /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s
1339    /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
1340    /// rounding mode.
1341    ///
1342    /// $$
1343    /// f(x) = \tanh x+\varepsilon.
1344    /// $$
1345    /// - If $\tanh x$ is zero or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
1346    /// - If $\tanh x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |\tanh
1347    ///   x|\rfloor-p}$, where $p$ is the precision of the input.
1348    ///
1349    /// Special cases:
1350    /// - $f(\text{NaN})=\text{NaN}$
1351    /// - $f(\infty)=1.0$
1352    /// - $f(-\infty)=-1.0$
1353    /// - $f(0.0)=0.0$
1354    /// - $f(-0.0)=-0.0$
1355    ///
1356    /// See the [`Float::tanh_round`] documentation for information on overflow and underflow.
1357    ///
1358    /// If you want to use a rounding mode other than `Nearest`, consider using
1359    /// [`Float::tanh_round_ref`] instead. If you want to specify the output precision, consider
1360    /// using [`Float::tanh_prec_ref`]. If you want both of these things, consider using
1361    /// [`Float::tanh_prec_round_ref`].
1362    ///
1363    /// # Worst-case complexity
1364    /// $T(n) = O(n^{3/2} \log n \log\log n)$
1365    ///
1366    /// $M(n) = O(n \log n)$
1367    ///
1368    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
1369    ///
1370    /// # Examples
1371    /// ```
1372    /// use malachite_base::num::arithmetic::traits::Tanh;
1373    /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity};
1374    /// use malachite_float::Float;
1375    ///
1376    /// assert!((&Float::NAN).tanh().is_nan());
1377    /// assert_eq!((&Float::INFINITY).tanh(), 1);
1378    /// assert_eq!((&Float::NEGATIVE_INFINITY).tanh(), -1);
1379    /// assert_eq!(
1380    ///     (&Float::from_unsigned_prec(1u32, 100).0).tanh().to_string(),
1381    ///     "0.76159415595576488811945828260469"
1382    /// );
1383    /// ```
1384    #[inline]
1385    fn tanh(self) -> Float {
1386        self.tanh_prec_round_ref(self.significant_bits(), Nearest).0
1387    }
1388}
1389
1390impl TanhAssign for Float {
1391    /// Computes $\tanh x$, the hyperbolic tangent of a [`Float`], in place.
1392    ///
1393    /// If the output has a precision, it is the precision of the input. If the hyperbolic tangent
1394    /// is equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s
1395    /// in its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
1396    /// rounding mode.
1397    ///
1398    /// $$
1399    /// x \gets \tanh x+\varepsilon.
1400    /// $$
1401    /// - If $\tanh x$ is zero or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
1402    /// - If $\tanh x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |\tanh
1403    ///   x|\rfloor-p}$, where $p$ is the precision of the input.
1404    ///
1405    /// See the [`Float::tanh`] documentation for information on special cases, overflow, and
1406    /// underflow.
1407    ///
1408    /// If you want to use a rounding mode other than `Nearest`, consider using
1409    /// [`Float::tanh_round_assign`] instead. If you want to specify the output precision, consider
1410    /// using [`Float::tanh_prec_assign`]. If you want both of these things, consider using
1411    /// [`Float::tanh_prec_round_assign`].
1412    ///
1413    /// # Worst-case complexity
1414    /// $T(n) = O(n^{3/2} \log n \log\log n)$
1415    ///
1416    /// $M(n) = O(n \log n)$
1417    ///
1418    /// where $T$ is time, $M$ is additional memory, and $n$ is `self.significant_bits()`.
1419    ///
1420    /// # Examples
1421    /// ```
1422    /// use malachite_base::num::arithmetic::traits::TanhAssign;
1423    /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity};
1424    /// use malachite_float::Float;
1425    ///
1426    /// let mut x = Float::NAN;
1427    /// x.tanh_assign();
1428    /// assert!(x.is_nan());
1429    ///
1430    /// let mut x = Float::INFINITY;
1431    /// x.tanh_assign();
1432    /// assert_eq!(x, 1);
1433    ///
1434    /// let mut x = Float::NEGATIVE_INFINITY;
1435    /// x.tanh_assign();
1436    /// assert_eq!(x, -1);
1437    ///
1438    /// let mut x = Float::from_unsigned_prec(1u32, 100).0;
1439    /// x.tanh_assign();
1440    /// assert_eq!(x.to_string(), "0.76159415595576488811945828260469");
1441    /// ```
1442    #[inline]
1443    fn tanh_assign(&mut self) {
1444        let prec = self.significant_bits();
1445        self.tanh_prec_round_assign(prec, Nearest);
1446    }
1447}
1448
1449/// Computes $\tanh x$, the hyperbolic tangent of a primitive float. The result is correctly
1450/// rounded.
1451///
1452/// $$
1453/// f(x) = \tanh x+\varepsilon.
1454/// $$
1455/// - If $\tanh x$ is zero or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
1456/// - If $\tanh x$ is nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |\tanh x|\rfloor-p}$, where
1457///   $p$ is the precision of the output (typically 24 if `T` is a [`f32`] and 53 if `T` is a
1458///   [`f64`], but less if the output is subnormal).
1459///
1460/// Special cases:
1461/// - $f(\text{NaN})=\text{NaN}$
1462/// - $f(\infty)=1.0$
1463/// - $f(-\infty)=-1.0$
1464/// - $f(0.0)=0.0$
1465/// - $f(-0.0)=-0.0$
1466///
1467/// Neither overflow nor underflow is possible. The result is subnormal only when $x$ is, and then
1468/// it is $x$ itself.
1469///
1470/// # Worst-case complexity
1471/// Constant time and additional memory.
1472///
1473/// # Examples
1474/// ```
1475/// use malachite_base::num::basic::traits::NegativeInfinity;
1476/// use malachite_base::num::float::NiceFloat;
1477/// use malachite_float::float::arithmetic::tanh::primitive_float_tanh;
1478///
1479/// assert!(primitive_float_tanh(f32::NAN).is_nan());
1480/// assert_eq!(
1481///     NiceFloat(primitive_float_tanh(f32::INFINITY)),
1482///     NiceFloat(1.0)
1483/// );
1484/// assert_eq!(
1485///     NiceFloat(primitive_float_tanh(f32::NEGATIVE_INFINITY)),
1486///     NiceFloat(-1.0)
1487/// );
1488/// assert_eq!(NiceFloat(primitive_float_tanh(-0.0f32)), NiceFloat(-0.0));
1489/// assert_eq!(
1490///     NiceFloat(primitive_float_tanh(1.0f32)),
1491///     NiceFloat(0.7615942)
1492/// );
1493/// assert_eq!(
1494///     NiceFloat(primitive_float_tanh(-1.0f64)),
1495///     NiceFloat(-0.7615941559557649)
1496/// );
1497/// assert_eq!(NiceFloat(primitive_float_tanh(20.0f64)), NiceFloat(1.0));
1498/// ```
1499#[inline]
1500#[allow(clippy::type_repetition_in_bounds)]
1501pub fn primitive_float_tanh<T: PrimitiveFloat>(x: T) -> T
1502where
1503    Float: From<T> + PartialOrd<T>,
1504    for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
1505{
1506    emulate_float_to_float_fn(Float::tanh_prec, x)
1507}
1508
1509/// Computes $\tanh x$, the hyperbolic tangent of a [`Rational`], returning the result as a
1510/// primitive float. The result is correctly rounded.
1511///
1512/// $$
1513/// f(x) = \tanh x+\varepsilon.
1514/// $$
1515/// - If $\tanh x$ is zero, $\varepsilon$ may be ignored or assumed to be 0.
1516/// - If $\tanh x$ is nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |\tanh x|\rfloor-p}$, where
1517///   $p$ is the precision of the output (typically 24 if `T` is a [`f32`] and 53 if `T` is a
1518///   [`f64`], but less if the output is subnormal).
1519///
1520/// Special cases:
1521/// - $f(0)=0.0$
1522///
1523/// Overflow is not possible, since the result lies in $(-1, 1)$. An `x` of small enough magnitude
1524/// underflows to `0.0` or `-0.0`.
1525///
1526/// # Worst-case complexity
1527/// $T(m) = O(m (\log m)^2 \log\log m)$
1528///
1529/// $M(m) = O(m \log m)$
1530///
1531/// where $T$ is time, $M$ is additional memory, and $m$ is `x.significant_bits()`.
1532///
1533/// # Examples
1534/// ```
1535/// use malachite_base::num::basic::traits::Zero;
1536/// use malachite_base::num::float::NiceFloat;
1537/// use malachite_float::float::arithmetic::tanh::primitive_float_tanh_rational;
1538/// use malachite_q::Rational;
1539///
1540/// assert_eq!(
1541///     NiceFloat(primitive_float_tanh_rational::<f64>(&Rational::ZERO)),
1542///     NiceFloat(0.0)
1543/// );
1544/// assert_eq!(
1545///     NiceFloat(primitive_float_tanh_rational::<f64>(
1546///         &Rational::from_unsigneds(1u8, 3)
1547///     )),
1548///     NiceFloat(0.32151273753163434)
1549/// );
1550/// assert_eq!(
1551///     NiceFloat(primitive_float_tanh_rational::<f64>(&Rational::from(
1552///         -10000
1553///     ))),
1554///     NiceFloat(-1.0)
1555/// );
1556/// ```
1557#[inline]
1558#[allow(clippy::type_repetition_in_bounds)]
1559pub fn primitive_float_tanh_rational<T: PrimitiveFloat>(x: &Rational) -> T
1560where
1561    Float: PartialOrd<T>,
1562    for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
1563{
1564    emulate_rational_to_float_fn(Float::tanh_rational_prec_ref, x)
1565}