Skip to main content

malachite_float/arithmetic/
log_base_10_1_plus_x.rs

1// Copyright © 2026 Mikhail Hogrefe
2//
3// This file is part of Malachite.
4//
5// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
6// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
7// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
8
9use crate::InnerFloat::{Infinity, NaN, Zero};
10use crate::arithmetic::log_base_1_plus_x::log_base_1_plus_x_rational;
11use crate::{Float, emulate_float_to_float_fn, float_infinity, float_nan, float_negative_infinity};
12use core::cmp::Ordering::{self, *};
13use malachite_base::num::arithmetic::traits::{
14    CeilingLogBase2, LogBase10Of1PlusX, LogBase10Of1PlusXAssign,
15};
16use malachite_base::num::basic::floats::PrimitiveFloat;
17use malachite_base::num::basic::integers::PrimitiveInt;
18use malachite_base::num::comparison::traits::PartialOrdAbs;
19use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom};
20use malachite_base::num::logic::traits::SignificantBits;
21use malachite_base::rounding_modes::RoundingMode::{self, *};
22use malachite_nz::natural::arithmetic::float_extras::float_can_round;
23use malachite_nz::platform::Limb;
24
25// The computation of log_base_10_1_plus_x(x) is done by log_10(1 + x) = log_2(1 + x) / log_2(10).
26// The input is finite and greater than -1.
27//
28// This specializes `log_base_1_plus_x` to base 10. Like that function (and unlike the plain
29// `log_base_10`), it routes through `log_base_2_1_plus_x` rather than computing `log_10(1 + x)`
30// from `1 + x` directly, preserving accuracy when x is near 0 where `1 + x` would lose precision.
31// Since 10 = 2 * 5 is not a perfect power, `log_10(1 + x)` is rational only when `1 + x = 10^m` (m
32// a nonnegative integer, so x = 0 or x = 10^m - 1); those exact results are detected up front (the
33// Ziv loop could never certify an exactly-representable one). `log_2(10)` is irrational, so every
34// other result is strictly between `Float`s and the loop converges.
35fn log_base_10_1_plus_x_prec_round_normal(
36    x: &Float,
37    prec: u64,
38    rm: RoundingMode,
39) -> (Float, Ordering) {
40    // log_10(1 + x) is undefined for x < -1.
41    match x.partial_cmp(&-1i32).unwrap() {
42        // 1 + x = 0, so log_10(1 + x) = -infinity.
43        Equal => return (float_negative_infinity!(), Equal),
44        Less => return (float_nan!(), Equal),
45        _ => {}
46    }
47    // If 1 + x = 10^m, then log_10(1 + x) = m is rational and exact. `log_base_1_plus_x_rational`
48    // with base 10 returns `Some(m / 1)`.
49    if let Some(q) = log_base_1_plus_x_rational(x, 10) {
50        return Float::from_rational_prec_round(q, prec, rm);
51    }
52    // The result is irrational, so it is never exactly representable.
53    assert_ne!(rm, Exact, "Inexact log_base_10_1_plus_x");
54    const TEN: Float = Float::const_from_unsigned(10);
55    let min_exp = i64::from(Float::MIN_EXPONENT);
56    let mut working_prec = prec + 4 + prec.ceiling_log_base_2();
57    let mut increment = Limb::WIDTH;
58    loop {
59        // log_2(1 + x), correctly rounded to working_prec; always within the Float exponent range.
60        let num = x.log_base_2_1_plus_x_prec_ref(working_prec).0;
61        // log_2(10) > 1, correctly rounded to working_prec.
62        let den = TEN.log_base_2_prec_ref(working_prec).0;
63        // Dividing by log_2(10) > 1 only shrinks the magnitude (overflow is impossible), but can
64        // push the result below MIN_EXPONENT. When it underflows, the Ziv test below could never
65        // resolve it (the quotient clamps), so hand the rounding to div_prec_round, which clamps to
66        // zero or the minimum positive value per the rounding mode. The exact quotient exponent is
67        // only resolved in the narrow band where the cheap exponent bound is inconclusive (then
68        // e_num - e_den == min_exp - 1, so the result underflows iff |log_2(1 + x)| * 2^(1 -
69        // min_exp) < log_2(10)). The left shift only adjusts the exponent, avoiding a huge Rational
70        // conversion.
71        let e_num = i64::from(num.get_exponent().unwrap());
72        let e_den = i64::from(den.get_exponent().unwrap());
73        if e_num - e_den + 1 < min_exp
74            || (e_num - e_den < min_exp && (&num << u64::exact_from(1 - min_exp)).lt_abs(&den))
75        {
76            return num.div_prec_round(den, prec, rm);
77        }
78        // log_2(1 + x) / log_2(10), with three correctly-rounded operations (log_base_2_1_plus_x,
79        // log_base_2, and the division, each at most 1/2 ulp), so the relative error is below 2^(2
80        // - working_prec) and working_prec - 4 correct bits suffice for rounding.
81        let t = num.div_prec(den, working_prec).0;
82        if float_can_round(t.significand_ref().unwrap(), working_prec - 4, prec, rm) {
83            return Float::from_float_prec_round(t, prec, rm);
84        }
85        // Increase the precision.
86        working_prec += increment;
87        increment = working_prec >> 1;
88    }
89}
90
91impl Float {
92    /// Computes $\log_{10}(1+x)$, where $x$ is a [`Float`], rounding the result to the specified
93    /// precision and with the specified rounding mode. The [`Float`] is taken by value. An
94    /// [`Ordering`] is also returned, indicating whether the rounded value is less than, equal to,
95    /// or greater than the exact value. Although `NaN`s are not comparable to any [`Float`],
96    /// whenever this function returns a `NaN` it also returns `Equal`.
97    ///
98    /// $\log_{10}(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, `NaN` is returned.
99    ///
100    /// This computes $\log_2(1+x) / \log_2 10$, preserving accuracy for $x$ near 0.
101    ///
102    /// See [`RoundingMode`] for a description of the possible rounding modes.
103    ///
104    /// $$
105    /// f(x,p,m) = \log_{10}(1+x)+\varepsilon.
106    /// $$
107    /// - If $\log_{10}(1+x)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
108    ///   to be 0.
109    /// - If $\log_{10}(1+x)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
110    ///   2^{\lfloor\log_2 |\log_{10}(1+x)|\rfloor-p+1}$.
111    /// - If $\log_{10}(1+x)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
112    ///   2^{\lfloor\log_2 |\log_{10}(1+x)|\rfloor-p}$.
113    ///
114    /// If the output has a precision, it is `prec`.
115    ///
116    /// Special cases:
117    /// - $f(\text{NaN},p,m)=\text{NaN}$
118    /// - $f(\infty,p,m)=\infty$
119    /// - $f(-\infty,p,m)=\text{NaN}$
120    /// - $f(\pm0.0,p,m)=\pm0.0$
121    /// - $f(-1.0,p,m)=-\infty$
122    /// - $f(x,p,m)=\text{NaN}$ for $x<-1$
123    /// - $f(x,p,m)=m$ when $1+x=10^m$, rounded to precision $p$; the result is exact if and only if
124    ///   $m$ is representable with precision $p$ (for example $\log_{10}(1+9)=1$ when $x=9$ is
125    ///   exact)
126    ///
127    /// This function cannot overflow, but it can underflow.
128    ///
129    /// If you know you'll be using `Nearest`, consider using [`Float::log_base_10_1_plus_x_prec`]
130    /// instead. If you know that your target precision is the precision of the input, consider
131    /// using [`Float::log_base_10_1_plus_x_round`] instead. If both of these things are true,
132    /// consider using `(&Float).log_base_10_1_plus_x()` instead.
133    ///
134    /// # Worst-case complexity
135    /// $T(n) = O(n (\log n)^2 \log\log n)$
136    ///
137    /// $M(n) = O(n (\log n)^2)$
138    ///
139    /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
140    ///
141    /// # Panics
142    /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
143    /// with the given precision.
144    ///
145    /// # Examples
146    /// ```
147    /// use malachite_base::rounding_modes::RoundingMode::*;
148    /// use malachite_float::Float;
149    /// use std::cmp::Ordering::*;
150    ///
151    /// let (log, o) = Float::from(9).log_base_10_1_plus_x_prec_round(10, Exact);
152    /// assert_eq!(log.to_string(), "1.0"); // log_10(10) = 1
153    /// assert_eq!(o, Equal);
154    ///
155    /// let (log, o) = Float::from(1).log_base_10_1_plus_x_prec_round(20, Nearest);
156    /// assert_eq!(log.to_string(), "0.3010302"); // log_10(2)
157    /// assert_eq!(o, Greater);
158    /// ```
159    #[inline]
160    pub fn log_base_10_1_plus_x_prec_round(self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
161        assert_ne!(prec, 0);
162        match self {
163            Self(NaN | Infinity { sign: false }) => (float_nan!(), Equal),
164            float_infinity!() => (float_infinity!(), Equal),
165            Self(Zero { .. }) => (self, Equal),
166            _ => log_base_10_1_plus_x_prec_round_normal(&self, prec, rm),
167        }
168    }
169
170    /// Computes $\log_{10}(1+x)$, where $x$ is a [`Float`], rounding the result to the specified
171    /// precision and with the specified rounding mode. The [`Float`] is taken by reference. An
172    /// [`Ordering`] is also returned, indicating whether the rounded value is less than, equal to,
173    /// or greater than the exact value. Although `NaN`s are not comparable to any [`Float`],
174    /// whenever this function returns a `NaN` it also returns `Equal`.
175    ///
176    /// See [`Float::log_base_10_1_plus_x_prec_round`] for details, special cases, and a description
177    /// of the rounding behavior.
178    ///
179    /// # Worst-case complexity
180    /// $T(n) = O(n (\log n)^2 \log\log n)$
181    ///
182    /// $M(n) = O(n (\log n)^2)$
183    ///
184    /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
185    ///
186    /// # Panics
187    /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
188    /// with the given precision.
189    ///
190    /// # Examples
191    /// ```
192    /// use malachite_base::rounding_modes::RoundingMode::*;
193    /// use malachite_float::Float;
194    /// use std::cmp::Ordering::*;
195    ///
196    /// let (log, o) = (&Float::from(99)).log_base_10_1_plus_x_prec_round_ref(10, Exact);
197    /// assert_eq!(log.to_string(), "2.0"); // log_10(100) = 2
198    /// assert_eq!(o, Equal);
199    ///
200    /// let (log, o) = (&Float::from(1)).log_base_10_1_plus_x_prec_round_ref(20, Floor);
201    /// assert_eq!(log.to_string(), "0.3010297"); // log_10(2), rounded down
202    /// assert_eq!(o, Less);
203    /// ```
204    #[inline]
205    pub fn log_base_10_1_plus_x_prec_round_ref(
206        &self,
207        prec: u64,
208        rm: RoundingMode,
209    ) -> (Self, Ordering) {
210        assert_ne!(prec, 0);
211        match self {
212            Self(NaN | Infinity { sign: false }) => (float_nan!(), Equal),
213            float_infinity!() => (float_infinity!(), Equal),
214            Self(Zero { .. }) => (self.clone(), Equal),
215            _ => log_base_10_1_plus_x_prec_round_normal(self, prec, rm),
216        }
217    }
218
219    /// Computes $\log_{10}(1+x)$, where $x$ is a [`Float`], rounding the result to the nearest
220    /// value of the specified precision. The [`Float`] is taken by value. An [`Ordering`] is also
221    /// returned, indicating whether the rounded value is less than, equal to, or greater than the
222    /// exact value.
223    ///
224    /// See [`Float::log_base_10_1_plus_x_prec_round`] for details and special cases.
225    ///
226    /// # Worst-case complexity
227    /// $T(n) = O(n (\log n)^2 \log\log n)$
228    ///
229    /// $M(n) = O(n (\log n)^2)$
230    ///
231    /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
232    ///
233    /// # Panics
234    /// Panics if `prec` is zero.
235    ///
236    /// # Examples
237    /// ```
238    /// use malachite_float::Float;
239    /// use std::cmp::Ordering::*;
240    ///
241    /// let (log, o) = Float::from(9).log_base_10_1_plus_x_prec(10);
242    /// assert_eq!(log.to_string(), "1.0"); // log_10(10) = 1
243    /// assert_eq!(o, Equal);
244    ///
245    /// let (log, o) = Float::from(1).log_base_10_1_plus_x_prec(20);
246    /// assert_eq!(log.to_string(), "0.3010302"); // log_10(2)
247    /// assert_eq!(o, Greater);
248    /// ```
249    #[inline]
250    pub fn log_base_10_1_plus_x_prec(self, prec: u64) -> (Self, Ordering) {
251        self.log_base_10_1_plus_x_prec_round(prec, Nearest)
252    }
253
254    /// Computes $\log_{10}(1+x)$, where $x$ is a [`Float`], rounding the result to the nearest
255    /// value of the specified precision. The [`Float`] is taken by reference. An [`Ordering`] is
256    /// also returned, indicating whether the rounded value is less than, equal to, or greater than
257    /// the exact value.
258    ///
259    /// See [`Float::log_base_10_1_plus_x_prec_round`] for details and special cases.
260    ///
261    /// # Worst-case complexity
262    /// $T(n) = O(n (\log n)^2 \log\log n)$
263    ///
264    /// $M(n) = O(n (\log n)^2)$
265    ///
266    /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
267    ///
268    /// # Panics
269    /// Panics if `prec` is zero.
270    ///
271    /// # Examples
272    /// ```
273    /// use malachite_float::Float;
274    /// use std::cmp::Ordering::*;
275    ///
276    /// let (log, o) = (&Float::from(99)).log_base_10_1_plus_x_prec_ref(10);
277    /// assert_eq!(log.to_string(), "2.0"); // log_10(100) = 2
278    /// assert_eq!(o, Equal);
279    ///
280    /// let (log, o) = (&Float::from(7)).log_base_10_1_plus_x_prec_ref(30);
281    /// assert_eq!(log.to_string(), "0.903089987"); // log_10(8)
282    /// assert_eq!(o, Greater);
283    /// ```
284    #[inline]
285    pub fn log_base_10_1_plus_x_prec_ref(&self, prec: u64) -> (Self, Ordering) {
286        self.log_base_10_1_plus_x_prec_round_ref(prec, Nearest)
287    }
288
289    /// Computes $\log_{10}(1+x)$, where $x$ is a [`Float`], rounding the result to the precision of
290    /// the input and with the specified rounding mode. The [`Float`] is taken by value. An
291    /// [`Ordering`] is also returned, indicating whether the rounded value is less than, equal to,
292    /// or greater than the exact value.
293    ///
294    /// See [`Float::log_base_10_1_plus_x_prec_round`] for details and special cases.
295    ///
296    /// # Worst-case complexity
297    /// $T(n) = O(n (\log n)^2 \log\log n)$
298    ///
299    /// $M(n) = O(n (\log n)^2)$
300    ///
301    /// where $T$ is time, $M$ is additional memory, and $n$ is the precision of the input.
302    ///
303    /// # Panics
304    /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input's
305    /// precision.
306    ///
307    /// # Examples
308    /// ```
309    /// use malachite_base::rounding_modes::RoundingMode::*;
310    /// use malachite_float::Float;
311    /// use std::cmp::Ordering::*;
312    ///
313    /// let (log, o) = Float::from(9).log_base_10_1_plus_x_round(Exact);
314    /// assert_eq!(log.to_string(), "1.0"); // log_10(10) = 1
315    /// assert_eq!(o, Equal);
316    ///
317    /// let (log, o) = Float::from(99).log_base_10_1_plus_x_round(Exact);
318    /// assert_eq!(log.to_string(), "2.0"); // log_10(100) = 2
319    /// assert_eq!(o, Equal);
320    /// ```
321    #[inline]
322    pub fn log_base_10_1_plus_x_round(self, rm: RoundingMode) -> (Self, Ordering) {
323        let prec = self.significant_bits();
324        self.log_base_10_1_plus_x_prec_round(prec, rm)
325    }
326
327    /// Computes $\log_{10}(1+x)$, where $x$ is a [`Float`], rounding the result to the precision of
328    /// the input and with the specified rounding mode. The [`Float`] is taken by reference. An
329    /// [`Ordering`] is also returned, indicating whether the rounded value is less than, equal to,
330    /// or greater than the exact value.
331    ///
332    /// See [`Float::log_base_10_1_plus_x_prec_round`] for details and special cases.
333    ///
334    /// # Worst-case complexity
335    /// $T(n) = O(n (\log n)^2 \log\log n)$
336    ///
337    /// $M(n) = O(n (\log n)^2)$
338    ///
339    /// where $T$ is time, $M$ is additional memory, and $n$ is the precision of the input.
340    ///
341    /// # Panics
342    /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input's
343    /// precision.
344    ///
345    /// # Examples
346    /// ```
347    /// use malachite_base::rounding_modes::RoundingMode::*;
348    /// use malachite_float::Float;
349    /// use std::cmp::Ordering::*;
350    ///
351    /// let (log, o) = (&Float::from(99)).log_base_10_1_plus_x_round_ref(Exact);
352    /// assert_eq!(log.to_string(), "2.0"); // log_10(100) = 2
353    /// assert_eq!(o, Equal);
354    ///
355    /// let (log, o) = (&Float::from(9)).log_base_10_1_plus_x_round_ref(Exact);
356    /// assert_eq!(log.to_string(), "1.0"); // log_10(10) = 1
357    /// assert_eq!(o, Equal);
358    /// ```
359    #[inline]
360    pub fn log_base_10_1_plus_x_round_ref(&self, rm: RoundingMode) -> (Self, Ordering) {
361        self.log_base_10_1_plus_x_prec_round_ref(self.significant_bits(), rm)
362    }
363
364    /// Computes $\log_{10}(1+x)$, where $x$ is a [`Float`], in place, rounding the result to the
365    /// specified precision and with the specified rounding mode. An [`Ordering`] is returned,
366    /// indicating whether the rounded value is less than, equal to, or greater than the exact
367    /// value.
368    ///
369    /// See [`Float::log_base_10_1_plus_x_prec_round`] for details and special cases.
370    ///
371    /// # Worst-case complexity
372    /// $T(n) = O(n (\log n)^2 \log\log n)$
373    ///
374    /// $M(n) = O(n (\log n)^2)$
375    ///
376    /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
377    ///
378    /// # Panics
379    /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
380    /// with the given precision.
381    ///
382    /// # Examples
383    /// ```
384    /// use malachite_base::rounding_modes::RoundingMode::*;
385    /// use malachite_float::Float;
386    /// use std::cmp::Ordering::*;
387    ///
388    /// let mut x = Float::from(9);
389    /// assert_eq!(x.log_base_10_1_plus_x_prec_round_assign(10, Exact), Equal);
390    /// assert_eq!(x.to_string(), "1.0"); // log_10(10) = 1
391    ///
392    /// let mut x = Float::from(1);
393    /// assert_eq!(x.log_base_10_1_plus_x_prec_round_assign(20, Floor), Less);
394    /// assert_eq!(x.to_string(), "0.3010297"); // log_10(2), rounded down
395    /// ```
396    #[inline]
397    pub fn log_base_10_1_plus_x_prec_round_assign(
398        &mut self,
399        prec: u64,
400        rm: RoundingMode,
401    ) -> Ordering {
402        let (result, o) = core::mem::take(self).log_base_10_1_plus_x_prec_round(prec, rm);
403        *self = result;
404        o
405    }
406
407    /// Computes $\log_{10}(1+x)$, where $x$ is a [`Float`], in place, rounding the result to the
408    /// nearest value of the specified precision. An [`Ordering`] is returned, indicating whether
409    /// the rounded value is less than, equal to, or greater than the exact value.
410    ///
411    /// See [`Float::log_base_10_1_plus_x_prec_round`] for details and special cases.
412    ///
413    /// # Worst-case complexity
414    /// $T(n) = O(n (\log n)^2 \log\log n)$
415    ///
416    /// $M(n) = O(n (\log n)^2)$
417    ///
418    /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
419    ///
420    /// # Panics
421    /// Panics if `prec` is zero.
422    ///
423    /// # Examples
424    /// ```
425    /// use malachite_float::Float;
426    ///
427    /// let mut x = Float::from(9);
428    /// x.log_base_10_1_plus_x_prec_assign(10);
429    /// assert_eq!(x.to_string(), "1.0"); // log_10(10) = 1
430    ///
431    /// let mut x = Float::from(99);
432    /// x.log_base_10_1_plus_x_prec_assign(10);
433    /// assert_eq!(x.to_string(), "2.0"); // log_10(100) = 2
434    /// ```
435    #[inline]
436    pub fn log_base_10_1_plus_x_prec_assign(&mut self, prec: u64) -> Ordering {
437        self.log_base_10_1_plus_x_prec_round_assign(prec, Nearest)
438    }
439
440    /// Computes $\log_{10}(1+x)$, where $x$ is a [`Float`], in place, rounding the result to the
441    /// precision of the input and with the specified rounding mode. An [`Ordering`] is returned,
442    /// indicating whether the rounded value is less than, equal to, or greater than the exact
443    /// value.
444    ///
445    /// See [`Float::log_base_10_1_plus_x_prec_round`] for details and special cases.
446    ///
447    /// # Worst-case complexity
448    /// $T(n) = O(n (\log n)^2 \log\log n)$
449    ///
450    /// $M(n) = O(n (\log n)^2)$
451    ///
452    /// where $T$ is time, $M$ is additional memory, and $n$ is the precision of the input.
453    ///
454    /// # Panics
455    /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input's
456    /// precision.
457    ///
458    /// # Examples
459    /// ```
460    /// use malachite_base::rounding_modes::RoundingMode::*;
461    /// use malachite_float::Float;
462    ///
463    /// let mut x = Float::from(9);
464    /// x.log_base_10_1_plus_x_round_assign(Exact);
465    /// assert_eq!(x.to_string(), "1.0"); // log_10(10) = 1
466    ///
467    /// let mut x = Float::from(99);
468    /// x.log_base_10_1_plus_x_round_assign(Exact);
469    /// assert_eq!(x.to_string(), "2.0"); // log_10(100) = 2
470    /// ```
471    #[inline]
472    pub fn log_base_10_1_plus_x_round_assign(&mut self, rm: RoundingMode) -> Ordering {
473        let prec = self.significant_bits();
474        self.log_base_10_1_plus_x_prec_round_assign(prec, rm)
475    }
476}
477
478impl LogBase10Of1PlusX for Float {
479    type Output = Self;
480
481    /// Computes $\log_{10}(1+x)$, where $x$ is a [`Float`], rounding the result to the nearest
482    /// value of the input's precision. The [`Float`] is taken by value.
483    ///
484    /// $\log_{10}(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, `NaN` is returned. See
485    /// [`Float::log_base_10_1_plus_x_prec_round`] for the other special cases.
486    ///
487    /// # Worst-case complexity
488    /// $T(n) = O(n (\log n)^2 \log\log n)$
489    ///
490    /// $M(n) = O(n (\log n)^2)$
491    ///
492    /// where $T$ is time, $M$ is additional memory, and $n$ is the precision of the input.
493    ///
494    /// # Examples
495    /// ```
496    /// use malachite_base::num::arithmetic::traits::LogBase10Of1PlusX;
497    /// use malachite_float::Float;
498    ///
499    /// assert_eq!(Float::from(9).log_base_10_1_plus_x().to_string(), "1.0"); // log_10(10) = 1
500    /// assert_eq!(Float::from(99).log_base_10_1_plus_x().to_string(), "2.0"); // log_10(100) = 2
501    /// ```
502    #[inline]
503    fn log_base_10_1_plus_x(self) -> Self {
504        let prec = self.significant_bits();
505        self.log_base_10_1_plus_x_prec_round(prec, Nearest).0
506    }
507}
508
509impl LogBase10Of1PlusX for &Float {
510    type Output = Float;
511
512    /// Computes $\log_{10}(1+x)$, where $x$ is a [`Float`], rounding the result to the nearest
513    /// value of the input's precision. The [`Float`] is taken by reference.
514    ///
515    /// $\log_{10}(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, `NaN` is returned. See
516    /// [`Float::log_base_10_1_plus_x_prec_round`] for the other special cases.
517    ///
518    /// # Worst-case complexity
519    /// $T(n) = O(n (\log n)^2 \log\log n)$
520    ///
521    /// $M(n) = O(n (\log n)^2)$
522    ///
523    /// where $T$ is time, $M$ is additional memory, and $n$ is the precision of the input.
524    ///
525    /// # Examples
526    /// ```
527    /// use malachite_base::num::arithmetic::traits::LogBase10Of1PlusX;
528    /// use malachite_float::Float;
529    ///
530    /// assert_eq!((&Float::from(9)).log_base_10_1_plus_x().to_string(), "1.0"); // log_10(10) = 1
531    /// assert_eq!((&Float::from(99)).log_base_10_1_plus_x().to_string(), "2.0"); // log_10(100) = 2
532    /// ```
533    #[inline]
534    fn log_base_10_1_plus_x(self) -> Float {
535        self.log_base_10_1_plus_x_prec_round_ref(self.significant_bits(), Nearest)
536            .0
537    }
538}
539
540impl LogBase10Of1PlusXAssign for Float {
541    /// Replaces a [`Float`] $x$ with $\log_{10}(1+x)$, rounding the result to the nearest value of
542    /// the input's precision.
543    ///
544    /// $\log_{10}(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, `NaN` is returned. See
545    /// [`Float::log_base_10_1_plus_x_prec_round`] for the other special cases.
546    ///
547    /// # Worst-case complexity
548    /// $T(n) = O(n (\log n)^2 \log\log n)$
549    ///
550    /// $M(n) = O(n (\log n)^2)$
551    ///
552    /// where $T$ is time, $M$ is additional memory, and $n$ is the precision of the input.
553    ///
554    /// # Examples
555    /// ```
556    /// use malachite_base::num::arithmetic::traits::LogBase10Of1PlusXAssign;
557    /// use malachite_float::Float;
558    ///
559    /// let mut x = Float::from(9);
560    /// x.log_base_10_1_plus_x_assign();
561    /// assert_eq!(x.to_string(), "1.0"); // log_10(10) = 1
562    ///
563    /// let mut x = Float::from(99);
564    /// x.log_base_10_1_plus_x_assign();
565    /// assert_eq!(x.to_string(), "2.0"); // log_10(100) = 2
566    /// ```
567    #[inline]
568    fn log_base_10_1_plus_x_assign(&mut self) {
569        let prec = self.significant_bits();
570        self.log_base_10_1_plus_x_prec_round_assign(prec, Nearest);
571    }
572}
573
574/// Computes $\log_{10}(1+x)$, the base-10 logarithm of one plus a primitive float. Using this
575/// function is more accurate than computing `(1 + x).log10()`, both because $1+x$ may not be
576/// representable as a primitive float and because the standard library's `log10` is not always
577/// correctly rounded.
578///
579/// $\log_{10}(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, `NaN` is returned.
580///
581/// $$
582/// f(x) = \log_{10}(1+x)+\varepsilon.
583/// $$
584/// - If $\log_{10}(1+x)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be
585///   0.
586/// - If $\log_{10}(1+x)$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2
587///   |\log_{10}(1+x)|\rfloor-p}$, where $p$ is precision of the output (typically 24 if `T` is a
588///   [`f32`] and 53 if `T` is a [`f64`], but less if the output is subnormal).
589///
590/// Special cases:
591/// - $f(\text{NaN})=\text{NaN}$
592/// - $f(\infty)=\infty$
593/// - $f(-\infty)=\text{NaN}$
594/// - $f(\pm0.0)=\pm0.0$
595/// - $f(-1.0)=-\infty$
596/// - $f(x)=\text{NaN}$ for $x<-1$
597///
598/// This function can underflow (to a subnormal or zero) when $x$ is close to zero, but it cannot
599/// overflow.
600///
601/// # Worst-case complexity
602/// Constant time and additional memory.
603///
604/// # Examples
605/// ```
606/// use malachite_base::num::basic::traits::NegativeInfinity;
607/// use malachite_base::num::float::NiceFloat;
608/// use malachite_float::arithmetic::log_base_10_1_plus_x::primitive_float_log_base_10_1_plus_x;
609///
610/// assert!(primitive_float_log_base_10_1_plus_x(f32::NAN).is_nan());
611/// assert_eq!(
612///     NiceFloat(primitive_float_log_base_10_1_plus_x(f32::INFINITY)),
613///     NiceFloat(f32::INFINITY)
614/// );
615/// assert_eq!(
616///     NiceFloat(primitive_float_log_base_10_1_plus_x(-1.0f32)),
617///     NiceFloat(f32::NEGATIVE_INFINITY)
618/// );
619/// assert!(primitive_float_log_base_10_1_plus_x(-2.0f32).is_nan());
620/// // log_10(1 + 999) = log_10(1000) = 3
621/// assert_eq!(
622///     NiceFloat(primitive_float_log_base_10_1_plus_x(999.0f32)),
623///     NiceFloat(3.0)
624/// );
625/// // log_10(1 + 9) = log_10(10) = 1
626/// assert_eq!(
627///     NiceFloat(primitive_float_log_base_10_1_plus_x(9.0f32)),
628///     NiceFloat(1.0)
629/// );
630/// // log_10(1 + 1) = log_10(2)
631/// assert_eq!(
632///     NiceFloat(primitive_float_log_base_10_1_plus_x(1.0f32)),
633///     NiceFloat(std::f32::consts::LOG10_2)
634/// );
635/// ```
636#[inline]
637#[allow(clippy::type_repetition_in_bounds)]
638pub fn primitive_float_log_base_10_1_plus_x<T: PrimitiveFloat>(x: T) -> T
639where
640    Float: From<T> + PartialOrd<T>,
641    for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
642{
643    emulate_float_to_float_fn(Float::log_base_10_1_plus_x_prec, x)
644}