Skip to main content

malachite_float/arithmetic/
log_base_10.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::{
17    Float, emulate_float_to_float_fn, emulate_rational_to_float_fn, float_either_zero,
18    float_infinity, float_nan, float_negative_infinity,
19};
20use core::cmp::Ordering::{self, *};
21use malachite_base::num::arithmetic::traits::{
22    CeilingLogBase2, CheckedLogBase, LogBase10, LogBase10Assign, Sign,
23};
24use malachite_base::num::basic::floats::PrimitiveFloat;
25use malachite_base::num::basic::integers::PrimitiveInt;
26use malachite_base::num::basic::traits::Zero as ZeroTrait;
27use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom};
28use malachite_base::num::logic::traits::SignificantBits;
29use malachite_base::rounding_modes::RoundingMode::{self, *};
30use malachite_nz::natural::Natural;
31use malachite_nz::natural::arithmetic::float_extras::float_can_round;
32use malachite_nz::platform::Limb;
33use malachite_q::Rational;
34
35// Returns `Some(n)` when `x == 10^n` for some integer `n >= 1`. The input `x` must be finite,
36// positive, and not equal to 1.
37//
38// `log_base_10(10^n) = n` is an exactly-representable integer, but the Ziv loop in
39// `log_base_10_prec_round_normal` could never certify it (the computed quotient lands on a
40// representable value the rounding test cannot resolve), so the exact case must be detected up
41// front. This is the `10^n` exactness check from mpfr_log10. Unlike a general base, `10 = 2 * 5` is
42// not a perfect power, so `log_base_10(x)` is rational only when `x` is a power of 10, and then the
43// result is the integer `n` -- there are no dyadic results to handle.
44//
45// The check is balloon-safe. An exact `10^n` has bit length about `n * log2(10)`, but its odd part
46// (the only part stored in the significand) is `5^n`, needing `n * log2(5)` bits, so the bit length
47// is at most about `64 * prec`. When `x`'s exponent exceeds that bound, `x` is too large to be an
48// exact power of 10 and is left to the Ziv loop (which then converges, `x` not being a power of
49// 10), so `x` is materialized as an integer only when doing so is cheap.
50pub(crate) fn float_is_power_of_10(x: &Float) -> Option<u64> {
51    let e = i64::from(x.get_exponent().unwrap());
52    // x < 1 cannot equal 10^n for n >= 1, and only positive exponents can.
53    if e < 1 || u64::exact_from(e) > x.get_prec().unwrap().saturating_mul(64) {
54        return None;
55    }
56    // `Natural::try_from` fails unless `x` is a nonnegative integer.
57    let n = Natural::try_from(x).ok()?;
58    (&n).checked_log_base(&const { Natural::const_from(10) })
59}
60
61// The computation of log_base_10(x) is done by log_base_10(x) = ln(x) / ln(10).
62//
63// This is mpfr_log10 from log10.c, MPFR 4.3.0. The input is finite, nonzero, and positive.
64fn log_base_10_prec_round_normal(x: &Float, prec: u64, rm: RoundingMode) -> (Float, Ordering) {
65    // If x is 1, the result is 0.
66    if *x == 1u32 {
67        return (Float::ZERO, Equal);
68    }
69    // If x = 10^n for some n >= 1, log_base_10(x) = n is exact (though possibly subject to rounding
70    // at the target precision).
71    if let Some(n) = float_is_power_of_10(x) {
72        return Float::from_unsigned_prec_round(n, prec, rm);
73    }
74    // The result is irrational, so it is never exactly representable.
75    assert_ne!(rm, Exact, "Inexact log_base_10");
76    const TEN: Float = Float::const_from_unsigned(10);
77    // Compute the precision of the intermediary variable: the optimal number of bits, see
78    // algorithms.tex.
79    let mut working_prec = prec + 4 + prec.ceiling_log_base_2();
80    let mut increment = Limb::WIDTH;
81    loop {
82        // ln(x) / ln(10). ln(x), ln(10), and the division are each correctly rounded (at most 1/2
83        // ulp), so the relative error is below 2^(2 - working_prec) and working_prec - 4 correct
84        // bits suffice for rounding (mpfr_log10 uses Nt - 4).
85        let t = x
86            .ln_prec_ref(working_prec)
87            .0
88            .div_prec(TEN.ln_prec_ref(working_prec).0, working_prec)
89            .0;
90        if float_can_round(t.significand_ref().unwrap(), working_prec - 4, prec, rm) {
91            return Float::from_float_prec_round(t, prec, rm);
92        }
93        // Increase the precision.
94        working_prec += increment;
95        increment = working_prec >> 1;
96    }
97}
98
99// Computes log_base_10(x) for a positive `Rational` x whose logarithm is irrational, in a Ziv loop.
100//
101// log_base_10(x) = log_2(x) / log_2(10). As in log_base_rational, routing through
102// `log_base_2_rational` (rather than computing `ln(x) / ln(10)` directly) reuses its handling of x
103// near a power of 2 -- in particular x near 1, where the result is near 0 and a direct computation
104// would need a working precision proportional to how close x is to 1. log_2(x), log_2(10), and the
105// division are each correctly rounded (at most 1/2 ulp), so the relative error is below 2^(2 -
106// working_prec) and working_prec - 4 correct bits suffice for rounding.
107fn log_base_10_rational_prec_round_helper(
108    x: &Rational,
109    prec: u64,
110    rm: RoundingMode,
111) -> (Float, Ordering) {
112    const TEN: Float = Float::const_from_unsigned(10);
113    let mut working_prec = prec + 4 + prec.ceiling_log_base_2();
114    let mut increment = Limb::WIDTH;
115    loop {
116        let t = Float::log_base_2_rational_prec_ref(x, working_prec)
117            .0
118            .div_prec(TEN.log_base_2_prec_ref(working_prec).0, working_prec)
119            .0;
120        if float_can_round(t.significand_ref().unwrap(), working_prec - 4, prec, rm) {
121            return Float::from_float_prec_round(t, prec, rm);
122        }
123        // Increase the precision.
124        working_prec += increment;
125        increment = working_prec >> 1;
126    }
127}
128
129impl Float {
130    /// Computes $\log_{10} x$, where $x$ is a [`Float`], rounding the result to the specified
131    /// precision and with the specified rounding mode. The [`Float`] is taken by value. An
132    /// [`Ordering`] is also returned, indicating whether the rounded value is less than, equal to,
133    /// or greater than the exact value. Although `NaN`s are not comparable to any [`Float`],
134    /// whenever this function returns a `NaN` it also returns `Equal`.
135    ///
136    /// The base-10 logarithm of any nonzero negative number is `NaN`.
137    ///
138    /// See [`RoundingMode`] for a description of the possible rounding modes.
139    ///
140    /// $$
141    /// f(x,p,m) = \log_{10} x+\varepsilon.
142    /// $$
143    /// - If $\log_{10} x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to
144    ///   be 0.
145    /// - If $\log_{10} x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
146    ///   2^{\lfloor\log_2 |\log_{10} x|\rfloor-p+1}$.
147    /// - If $\log_{10} x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
148    ///   2^{\lfloor\log_2 |\log_{10} x|\rfloor-p}$.
149    ///
150    /// If the output has a precision, it is `prec`.
151    ///
152    /// Special cases:
153    /// - $f(\text{NaN},p,m)=\text{NaN}$
154    /// - $f(\infty,p,m)=\infty$
155    /// - $f(-\infty,p,m)=\text{NaN}$
156    /// - $f(\pm0.0,p,m)=-\infty$
157    /// - $f(1.0,p,m)=0.0$, and the result is exact
158    /// - $f(10^n,p,m)=n$, rounded to precision $p$; the result is exact if and only if $n$ is
159    ///   representable with precision $p$
160    /// - $f(x,p,m)=\text{NaN}$ for $x<0$
161    ///
162    /// If you know you'll be using `Nearest`, consider using [`Float::log_base_10_prec`] instead.
163    /// If you know that your target precision is the precision of the input, consider using
164    /// [`Float::log_base_10_round`] instead. If both of these things are true, consider using
165    /// [`Float::log_base_10`] instead.
166    ///
167    /// # Worst-case complexity
168    /// $T(n) = O(n (\log n)^2 \log\log n)$
169    ///
170    /// $M(n) = O(n (\log n)^2)$
171    ///
172    /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
173    ///
174    /// # Panics
175    /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
176    /// with the given precision.
177    ///
178    /// # Examples
179    /// ```
180    /// use malachite_base::rounding_modes::RoundingMode::*;
181    /// use malachite_float::Float;
182    /// use std::cmp::Ordering::*;
183    ///
184    /// let (log, o) = Float::from(1000).log_base_10_prec_round(10, Nearest);
185    /// assert_eq!(log.to_string(), "3.0");
186    /// assert_eq!(o, Equal);
187    ///
188    /// let (log, o) = Float::from(50).log_base_10_prec_round(10, Floor);
189    /// assert_eq!(log.to_string(), "1.697");
190    /// assert_eq!(o, Less);
191    ///
192    /// let (log, o) = Float::from(50).log_base_10_prec_round(10, Ceiling);
193    /// assert_eq!(log.to_string(), "1.699");
194    /// assert_eq!(o, Greater);
195    /// ```
196    #[inline]
197    pub fn log_base_10_prec_round(self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
198        assert_ne!(prec, 0);
199        match self {
200            Self(NaN | Infinity { sign: false } | Finite { sign: false, .. }) => {
201                (float_nan!(), Equal)
202            }
203            float_either_zero!() => (float_negative_infinity!(), Equal),
204            float_infinity!() => (float_infinity!(), Equal),
205            _ => log_base_10_prec_round_normal(&self, prec, rm),
206        }
207    }
208
209    /// Computes $\log_{10} x$, where $x$ is a [`Float`], rounding the result to the specified
210    /// precision and with the specified rounding mode. The [`Float`] is taken by reference. An
211    /// [`Ordering`] is also returned, indicating whether the rounded value is less than, equal to,
212    /// or greater than the exact value. Although `NaN`s are not comparable to any [`Float`],
213    /// whenever this function returns a `NaN` it also returns `Equal`.
214    ///
215    /// See [`Float::log_base_10_prec_round`] for details, special cases, and a description of the
216    /// rounding behavior.
217    ///
218    /// # Worst-case complexity
219    /// $T(n) = O(n (\log n)^2 \log\log n)$
220    ///
221    /// $M(n) = O(n (\log n)^2)$
222    ///
223    /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
224    ///
225    /// # Panics
226    /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
227    /// with the given precision.
228    ///
229    /// # Examples
230    /// ```
231    /// use malachite_base::rounding_modes::RoundingMode::*;
232    /// use malachite_float::Float;
233    /// use std::cmp::Ordering::*;
234    ///
235    /// let (log, o) = Float::from(1000).log_base_10_prec_round_ref(10, Nearest);
236    /// assert_eq!(log.to_string(), "3.0");
237    /// assert_eq!(o, Equal);
238    /// ```
239    #[inline]
240    pub fn log_base_10_prec_round_ref(&self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
241        assert_ne!(prec, 0);
242        match self {
243            Self(NaN | Infinity { sign: false } | Finite { sign: false, .. }) => {
244                (float_nan!(), Equal)
245            }
246            float_either_zero!() => (float_negative_infinity!(), Equal),
247            float_infinity!() => (float_infinity!(), Equal),
248            _ => log_base_10_prec_round_normal(self, prec, rm),
249        }
250    }
251
252    /// Computes $\log_{10} x$, where $x$ is a [`Float`], rounding the result to the nearest value
253    /// of the specified precision. The [`Float`] is taken by value. An [`Ordering`] is also
254    /// returned, indicating whether the rounded value is less than, equal to, or greater than the
255    /// exact value.
256    ///
257    /// See [`Float::log_base_10_prec_round`] for details and special cases.
258    ///
259    /// # Worst-case complexity
260    /// $T(n) = O(n (\log n)^2 \log\log n)$
261    ///
262    /// $M(n) = O(n (\log n)^2)$
263    ///
264    /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
265    ///
266    /// # Panics
267    /// Panics if `prec` is zero.
268    ///
269    /// # Examples
270    /// ```
271    /// use malachite_float::Float;
272    /// use std::cmp::Ordering::*;
273    ///
274    /// let (log, o) = Float::from(50).log_base_10_prec(10);
275    /// assert_eq!(log.to_string(), "1.699");
276    /// assert_eq!(o, Greater);
277    /// ```
278    #[inline]
279    pub fn log_base_10_prec(self, prec: u64) -> (Self, Ordering) {
280        self.log_base_10_prec_round(prec, Nearest)
281    }
282
283    /// Computes $\log_{10} x$, where $x$ is a [`Float`], rounding the result to the nearest value
284    /// of the specified precision. The [`Float`] is taken by reference. An [`Ordering`] is also
285    /// returned, indicating whether the rounded value is less than, equal to, or greater than the
286    /// exact value.
287    ///
288    /// See [`Float::log_base_10_prec_round`] for details and special cases.
289    ///
290    /// # Worst-case complexity
291    /// $T(n) = O(n (\log n)^2 \log\log n)$
292    ///
293    /// $M(n) = O(n (\log n)^2)$
294    ///
295    /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
296    ///
297    /// # Panics
298    /// Panics if `prec` is zero.
299    ///
300    /// # Examples
301    /// ```
302    /// use malachite_float::Float;
303    /// use std::cmp::Ordering::*;
304    ///
305    /// let (log, o) = Float::from(50).log_base_10_prec_ref(10);
306    /// assert_eq!(log.to_string(), "1.699");
307    /// assert_eq!(o, Greater);
308    /// ```
309    #[inline]
310    pub fn log_base_10_prec_ref(&self, prec: u64) -> (Self, Ordering) {
311        self.log_base_10_prec_round_ref(prec, Nearest)
312    }
313
314    /// Computes $\log_{10} x$, where $x$ is a [`Float`], rounding the result to the precision of
315    /// the input and with the specified rounding mode. The [`Float`] is taken by value. An
316    /// [`Ordering`] is also returned, indicating whether the rounded value is less than, equal to,
317    /// or greater than the exact value.
318    ///
319    /// See [`Float::log_base_10_prec_round`] for details and special cases.
320    ///
321    /// # Worst-case complexity
322    /// $T(n) = O(n (\log n)^2 \log\log n)$
323    ///
324    /// $M(n) = O(n (\log n)^2)$
325    ///
326    /// where $T$ is time, $M$ is additional memory, and $n$ is the precision of the input.
327    ///
328    /// # Panics
329    /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input's
330    /// precision.
331    ///
332    /// # Examples
333    /// ```
334    /// use malachite_base::rounding_modes::RoundingMode::*;
335    /// use malachite_float::Float;
336    /// use std::cmp::Ordering::*;
337    ///
338    /// let (log, o) = Float::from(1000).log_base_10_round(Floor);
339    /// assert_eq!(log.to_string(), "3.0");
340    /// assert_eq!(o, Equal);
341    /// ```
342    #[inline]
343    pub fn log_base_10_round(self, rm: RoundingMode) -> (Self, Ordering) {
344        let prec = self.significant_bits();
345        self.log_base_10_prec_round(prec, rm)
346    }
347
348    /// Computes $\log_{10} x$, where $x$ is a [`Float`], rounding the result to the precision of
349    /// the input and with the specified rounding mode. The [`Float`] is taken by reference. An
350    /// [`Ordering`] is also returned, indicating whether the rounded value is less than, equal to,
351    /// or greater than the exact value.
352    ///
353    /// See [`Float::log_base_10_prec_round`] for details and special cases.
354    ///
355    /// # Worst-case complexity
356    /// $T(n) = O(n (\log n)^2 \log\log n)$
357    ///
358    /// $M(n) = O(n (\log n)^2)$
359    ///
360    /// where $T$ is time, $M$ is additional memory, and $n$ is the precision of the input.
361    ///
362    /// # Panics
363    /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input's
364    /// precision.
365    ///
366    /// # Examples
367    /// ```
368    /// use malachite_base::rounding_modes::RoundingMode::*;
369    /// use malachite_float::Float;
370    /// use std::cmp::Ordering::*;
371    ///
372    /// let (log, o) = Float::from(100).log_base_10_round_ref(Ceiling);
373    /// assert_eq!(log.to_string(), "2.0");
374    /// assert_eq!(o, Equal);
375    /// ```
376    #[inline]
377    pub fn log_base_10_round_ref(&self, rm: RoundingMode) -> (Self, Ordering) {
378        self.log_base_10_prec_round_ref(self.significant_bits(), rm)
379    }
380
381    /// Computes $\log_{10} x$, where $x$ is a [`Float`], in place, rounding the result to the
382    /// specified precision and with the specified rounding mode. An [`Ordering`] is returned,
383    /// indicating whether the rounded value is less than, equal to, or greater than the exact
384    /// value.
385    ///
386    /// See [`Float::log_base_10_prec_round`] for details and special cases.
387    ///
388    /// # Worst-case complexity
389    /// $T(n) = O(n (\log n)^2 \log\log n)$
390    ///
391    /// $M(n) = O(n (\log n)^2)$
392    ///
393    /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
394    ///
395    /// # Panics
396    /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
397    /// with the given precision.
398    ///
399    /// # Examples
400    /// ```
401    /// use malachite_base::rounding_modes::RoundingMode::*;
402    /// use malachite_float::Float;
403    /// use std::cmp::Ordering::*;
404    ///
405    /// let mut x = Float::from(50);
406    /// let o = x.log_base_10_prec_round_assign(10, Floor);
407    /// assert_eq!(x.to_string(), "1.697");
408    /// assert_eq!(o, Less);
409    /// ```
410    #[inline]
411    pub fn log_base_10_prec_round_assign(&mut self, prec: u64, rm: RoundingMode) -> Ordering {
412        let (result, o) = core::mem::take(self).log_base_10_prec_round(prec, rm);
413        *self = result;
414        o
415    }
416
417    /// Computes $\log_{10} x$, where $x$ is a [`Float`], in place, rounding the result to the
418    /// nearest value of the specified precision. An [`Ordering`] is returned, indicating whether
419    /// the rounded value is less than, equal to, or greater than the exact value.
420    ///
421    /// See [`Float::log_base_10_prec_round`] for details and special cases.
422    ///
423    /// # Worst-case complexity
424    /// $T(n) = O(n (\log n)^2 \log\log n)$
425    ///
426    /// $M(n) = O(n (\log n)^2)$
427    ///
428    /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
429    ///
430    /// # Panics
431    /// Panics if `prec` is zero.
432    ///
433    /// # Examples
434    /// ```
435    /// use malachite_float::Float;
436    /// use std::cmp::Ordering::*;
437    ///
438    /// let mut x = Float::from(1000);
439    /// let o = x.log_base_10_prec_assign(10);
440    /// assert_eq!(x.to_string(), "3.0");
441    /// assert_eq!(o, Equal);
442    /// ```
443    #[inline]
444    pub fn log_base_10_prec_assign(&mut self, prec: u64) -> Ordering {
445        self.log_base_10_prec_round_assign(prec, Nearest)
446    }
447
448    /// Computes $\log_{10} x$, where $x$ is a [`Float`], in place, rounding the result to the
449    /// precision of the input and with the specified rounding mode. An [`Ordering`] is returned,
450    /// indicating whether the rounded value is less than, equal to, or greater than the exact
451    /// value.
452    ///
453    /// See [`Float::log_base_10_prec_round`] for details and special cases.
454    ///
455    /// # Worst-case complexity
456    /// $T(n) = O(n (\log n)^2 \log\log n)$
457    ///
458    /// $M(n) = O(n (\log n)^2)$
459    ///
460    /// where $T$ is time, $M$ is additional memory, and $n$ is the precision of the input.
461    ///
462    /// # Panics
463    /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input's
464    /// precision.
465    ///
466    /// # Examples
467    /// ```
468    /// use malachite_base::rounding_modes::RoundingMode::*;
469    /// use malachite_float::Float;
470    /// use std::cmp::Ordering::*;
471    ///
472    /// let mut x = Float::from(100);
473    /// let o = x.log_base_10_round_assign(Nearest);
474    /// assert_eq!(x.to_string(), "2.0");
475    /// assert_eq!(o, Equal);
476    /// ```
477    #[inline]
478    pub fn log_base_10_round_assign(&mut self, rm: RoundingMode) -> Ordering {
479        let prec = self.significant_bits();
480        self.log_base_10_prec_round_assign(prec, rm)
481    }
482
483    /// Computes $\log_{10} x$, where $x$ is a [`Rational`], rounding the result to the specified
484    /// precision and with the specified rounding mode and returning the result as a [`Float`]. The
485    /// [`Rational`] is taken by value. An [`Ordering`] is also returned, indicating whether the
486    /// rounded value is less than, equal to, or greater than the exact value. Although `NaN`s are
487    /// not comparable to any [`Float`], whenever this function returns a `NaN` it also returns
488    /// `Equal`.
489    ///
490    /// The base-10 logarithm of any negative number is `NaN`.
491    ///
492    /// Inputs of any magnitude are handled, including [`Rational`]s whose magnitudes are too large
493    /// or too small to be representable as [`Float`]s. Neither overflow nor underflow of the output
494    /// is possible.
495    ///
496    /// See [`Float::log_base_10_prec_round`] for details and a description of the rounding
497    /// behavior.
498    ///
499    /// Special cases:
500    /// - $f(0,p,m)=-\infty$
501    /// - $f(x,p,m)=\text{NaN}$ for $x<0$
502    /// - $f(1,p,m)=0.0$, and the result is exact
503    /// - $f(10^n,p,m)=n$, rounded to precision $p$; the result is exact if and only if the integer
504    ///   $n$ is representable with precision $p$. This includes negative powers of 10 like $1/100$,
505    ///   and powers of 10 whose exponents lie far outside the exponent range of [`Float`].
506    ///
507    /// # Worst-case complexity
508    /// $T(n) = O(n (\log n)^2 \log\log n)$
509    ///
510    /// $M(n) = O(n (\log n)^2)$
511    ///
512    /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
513    ///
514    /// # Panics
515    /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
516    /// with the given precision. (The result is exactly representable if and only if $x \leq 0$ or
517    /// $x$ is a power of 10 whose base-10 logarithm is representable with the given precision.)
518    ///
519    /// # Examples
520    /// ```
521    /// use malachite_base::rounding_modes::RoundingMode::*;
522    /// use malachite_float::Float;
523    /// use malachite_q::Rational;
524    /// use std::cmp::Ordering::*;
525    ///
526    /// let (log, o) = Float::log_base_10_rational_prec_round(Rational::from(1000), 10, Exact);
527    /// assert_eq!(log.to_string(), "3.0");
528    /// assert_eq!(o, Equal);
529    ///
530    /// let (log, o) =
531    ///     Float::log_base_10_rational_prec_round(Rational::from_signeds(1, 100), 10, Exact);
532    /// assert_eq!(log.to_string(), "-2.0"); // log_10(1/100) = -2
533    /// assert_eq!(o, Equal);
534    /// ```
535    #[allow(clippy::needless_pass_by_value)]
536    #[inline]
537    pub fn log_base_10_rational_prec_round(
538        x: Rational,
539        prec: u64,
540        rm: RoundingMode,
541    ) -> (Self, Ordering) {
542        Self::log_base_10_rational_prec_round_ref(&x, prec, rm)
543    }
544
545    /// Computes $\log_{10} x$, where $x$ is a [`Rational`], rounding the result to the specified
546    /// precision and with the specified rounding mode and returning the result as a [`Float`]. The
547    /// [`Rational`] is taken by reference. An [`Ordering`] is also returned, indicating whether the
548    /// rounded value is less than, equal to, or greater than the exact value. Although `NaN`s are
549    /// not comparable to any [`Float`], whenever this function returns a `NaN` it also returns
550    /// `Equal`.
551    ///
552    /// See [`Float::log_base_10_rational_prec_round`] for details, special cases, and a description
553    /// of the rounding behavior.
554    ///
555    /// # Worst-case complexity
556    /// $T(n) = O(n (\log n)^2 \log\log n)$
557    ///
558    /// $M(n) = O(n (\log n)^2)$
559    ///
560    /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
561    ///
562    /// # Panics
563    /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
564    /// with the given precision.
565    ///
566    /// # Examples
567    /// ```
568    /// use malachite_base::rounding_modes::RoundingMode::*;
569    /// use malachite_float::Float;
570    /// use malachite_q::Rational;
571    /// use std::cmp::Ordering::*;
572    ///
573    /// let (log, o) =
574    ///     Float::log_base_10_rational_prec_round_ref(&Rational::from(1000), 10, Nearest);
575    /// assert_eq!(log.to_string(), "3.0");
576    /// assert_eq!(o, Equal);
577    /// ```
578    pub fn log_base_10_rational_prec_round_ref(
579        x: &Rational,
580        prec: u64,
581        rm: RoundingMode,
582    ) -> (Self, Ordering) {
583        assert_ne!(prec, 0);
584        match x.sign() {
585            Equal => return (float_negative_infinity!(), Equal),
586            Less => return (float_nan!(), Equal),
587            Greater => {}
588        }
589        // If x = 10^m, then log_base_10(x) = m is an exact integer (m may be negative, for x < 1).
590        // The Ziv loop could never certify it (see float_is_power_of_10 for the Float analog).
591        if let Some(m) = x.checked_log_base(10) {
592            return Self::from_signed_prec_round(m, prec, rm);
593        }
594        // The result is irrational, so it is never exactly representable.
595        assert_ne!(rm, Exact, "Inexact log_base_10");
596        log_base_10_rational_prec_round_helper(x, prec, rm)
597    }
598
599    /// Computes $\log_{10} x$, where $x$ is a [`Rational`], rounding the result to the nearest
600    /// value of the specified precision and returning the result as a [`Float`]. The [`Rational`]
601    /// is taken by value. An [`Ordering`] is also returned, indicating whether the rounded value is
602    /// less than, equal to, or greater than the exact value.
603    ///
604    /// See [`Float::log_base_10_rational_prec_round`] for details and special cases.
605    ///
606    /// # Worst-case complexity
607    /// $T(n) = O(n (\log n)^2 \log\log n)$
608    ///
609    /// $M(n) = O(n (\log n)^2)$
610    ///
611    /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
612    ///
613    /// # Panics
614    /// Panics if `prec` is zero.
615    ///
616    /// # Examples
617    /// ```
618    /// use malachite_float::Float;
619    /// use malachite_q::Rational;
620    /// use std::cmp::Ordering::*;
621    ///
622    /// let (log, o) = Float::log_base_10_rational_prec(Rational::from_signeds(1, 100), 10);
623    /// assert_eq!(log.to_string(), "-2.0");
624    /// assert_eq!(o, Equal);
625    /// ```
626    #[inline]
627    pub fn log_base_10_rational_prec(x: Rational, prec: u64) -> (Self, Ordering) {
628        Self::log_base_10_rational_prec_round(x, prec, Nearest)
629    }
630
631    /// Computes $\log_{10} x$, where $x$ is a [`Rational`], rounding the result to the nearest
632    /// value of the specified precision and returning the result as a [`Float`]. The [`Rational`]
633    /// is taken by reference. An [`Ordering`] is also returned, indicating whether the rounded
634    /// value is less than, equal to, or greater than the exact value.
635    ///
636    /// See [`Float::log_base_10_rational_prec_round`] for details and special cases.
637    ///
638    /// # Worst-case complexity
639    /// $T(n) = O(n (\log n)^2 \log\log n)$
640    ///
641    /// $M(n) = O(n (\log n)^2)$
642    ///
643    /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
644    ///
645    /// # Panics
646    /// Panics if `prec` is zero.
647    ///
648    /// # Examples
649    /// ```
650    /// use malachite_float::Float;
651    /// use malachite_q::Rational;
652    /// use std::cmp::Ordering::*;
653    ///
654    /// let (log, o) = Float::log_base_10_rational_prec_ref(&Rational::from(50), 10);
655    /// assert_eq!(log.to_string(), "1.699");
656    /// assert_eq!(o, Greater);
657    /// ```
658    #[inline]
659    pub fn log_base_10_rational_prec_ref(x: &Rational, prec: u64) -> (Self, Ordering) {
660        Self::log_base_10_rational_prec_round_ref(x, prec, Nearest)
661    }
662}
663
664impl LogBase10 for Float {
665    type Output = Self;
666
667    /// Computes $\log_{10} x$, where $x$ is a [`Float`], rounding the result to the nearest value
668    /// of the input's precision. The [`Float`] is taken by value.
669    ///
670    /// The base-10 logarithm of any nonzero negative number is `NaN`. See
671    /// [`Float::log_base_10_prec_round`] for the special cases.
672    ///
673    /// $$
674    /// f(x) = \log_{10} x+\varepsilon,
675    /// $$
676    /// where $|\varepsilon| \leq 2^{\lfloor\log_2 |\log_{10} x|\rfloor-p}$ and $p$ is the precision
677    /// of the input.
678    ///
679    /// # Worst-case complexity
680    /// $T(n) = O(n (\log n)^2 \log\log n)$
681    ///
682    /// $M(n) = O(n (\log n)^2)$
683    ///
684    /// where $T$ is time, $M$ is additional memory, and $n$ is the precision of the input.
685    ///
686    /// # Examples
687    /// ```
688    /// use malachite_base::num::arithmetic::traits::LogBase10;
689    /// use malachite_float::Float;
690    ///
691    /// assert_eq!(Float::from(1000).log_base_10().to_string(), "3.0");
692    /// assert_eq!(Float::from(100).log_base_10().to_string(), "2.0");
693    /// ```
694    #[inline]
695    fn log_base_10(self) -> Self {
696        let prec = self.significant_bits();
697        self.log_base_10_prec_round(prec, Nearest).0
698    }
699}
700
701impl LogBase10 for &Float {
702    type Output = Float;
703
704    /// Computes $\log_{10} x$, where $x$ is a [`Float`], rounding the result to the nearest value
705    /// of the input's precision. The [`Float`] is taken by reference.
706    ///
707    /// The base-10 logarithm of any nonzero negative number is `NaN`. See
708    /// [`Float::log_base_10_prec_round`] for the special cases.
709    ///
710    /// $$
711    /// f(x) = \log_{10} x+\varepsilon,
712    /// $$
713    /// where $|\varepsilon| \leq 2^{\lfloor\log_2 |\log_{10} x|\rfloor-p}$ and $p$ is the precision
714    /// of the input.
715    ///
716    /// # Worst-case complexity
717    /// $T(n) = O(n (\log n)^2 \log\log n)$
718    ///
719    /// $M(n) = O(n (\log n)^2)$
720    ///
721    /// where $T$ is time, $M$ is additional memory, and $n$ is the precision of the input.
722    ///
723    /// # Examples
724    /// ```
725    /// use malachite_base::num::arithmetic::traits::LogBase10;
726    /// use malachite_float::Float;
727    ///
728    /// assert_eq!((&Float::from(1000)).log_base_10().to_string(), "3.0");
729    /// ```
730    #[inline]
731    fn log_base_10(self) -> Float {
732        self.log_base_10_prec_round_ref(self.significant_bits(), Nearest)
733            .0
734    }
735}
736
737impl LogBase10Assign for Float {
738    /// Replaces a [`Float`] $x$ with $\log_{10} x$, rounding the result to the nearest value of the
739    /// input's precision.
740    ///
741    /// The base-10 logarithm of any nonzero negative number is `NaN`. See
742    /// [`Float::log_base_10_prec_round`] for the special cases.
743    ///
744    /// # Worst-case complexity
745    /// $T(n) = O(n (\log n)^2 \log\log n)$
746    ///
747    /// $M(n) = O(n (\log n)^2)$
748    ///
749    /// where $T$ is time, $M$ is additional memory, and $n$ is the precision of the input.
750    ///
751    /// # Examples
752    /// ```
753    /// use malachite_base::num::arithmetic::traits::LogBase10Assign;
754    /// use malachite_float::Float;
755    ///
756    /// let mut x = Float::from(1000);
757    /// x.log_base_10_assign();
758    /// assert_eq!(x.to_string(), "3.0");
759    /// ```
760    #[inline]
761    fn log_base_10_assign(&mut self) {
762        let prec = self.significant_bits();
763        self.log_base_10_prec_round_assign(prec, Nearest);
764    }
765}
766
767/// Computes $\log_{10} x$, the base-10 logarithm of a primitive float. Using this function is more
768/// accurate than using the primitive float `log10` function (the standard library's `log10` is not
769/// always correctly rounded).
770///
771/// The base-10 logarithm of any negative number is `NaN`.
772///
773/// $$
774/// f(x) = \log_{10} x+\varepsilon.
775/// $$
776/// - If $\log_{10} x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
777/// - If $\log_{10} x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |\log_{10}
778///   x|\rfloor-p}$, where $p$ is precision of the output (typically 24 if `T` is a [`f32`] and 53
779///   if `T` is a [`f64`], but less if the output is subnormal).
780///
781/// Special cases:
782/// - $f(\text{NaN})=\text{NaN}$
783/// - $f(\infty)=\infty$
784/// - $f(-\infty)=\text{NaN}$
785/// - $f(\pm0.0)=-\infty$
786/// - $f(1.0)=0.0$
787/// - $f(x)=\text{NaN}$ for $x<0$
788///
789/// Neither overflow nor underflow is possible.
790///
791/// # Worst-case complexity
792/// Constant time and additional memory.
793///
794/// # Examples
795/// ```
796/// use malachite_base::num::basic::traits::NegativeInfinity;
797/// use malachite_base::num::float::NiceFloat;
798/// use malachite_float::arithmetic::log_base_10::primitive_float_log_base_10;
799///
800/// assert!(primitive_float_log_base_10(f32::NAN).is_nan());
801/// assert_eq!(
802///     NiceFloat(primitive_float_log_base_10(f32::INFINITY)),
803///     NiceFloat(f32::INFINITY)
804/// );
805/// assert_eq!(
806///     NiceFloat(primitive_float_log_base_10(0.0f32)),
807///     NiceFloat(f32::NEGATIVE_INFINITY)
808/// );
809/// // log_10(1000) = 3
810/// assert_eq!(
811///     NiceFloat(primitive_float_log_base_10(1000.0f32)),
812///     NiceFloat(3.0)
813/// );
814/// // log_10(50)
815/// assert_eq!(
816///     NiceFloat(primitive_float_log_base_10(50.0f32)),
817///     NiceFloat(1.69897)
818/// );
819/// assert!(primitive_float_log_base_10(-1.0f32).is_nan());
820/// ```
821#[inline]
822#[allow(clippy::type_repetition_in_bounds)]
823pub fn primitive_float_log_base_10<T: PrimitiveFloat>(x: T) -> T
824where
825    Float: From<T> + PartialOrd<T>,
826    for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
827{
828    emulate_float_to_float_fn(Float::log_base_10_prec, x)
829}
830
831/// Computes $\log_{10} x$, the base-10 logarithm of a [`Rational`], returning a primitive float
832/// result.
833///
834/// If the logarithm is equidistant from two primitive floats, the primitive float with fewer 1s in
835/// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` rounding
836/// mode.
837///
838/// The base-10 logarithm of any negative number is `NaN`.
839///
840/// $$
841/// f(x) = \log_{10} x+\varepsilon.
842/// $$
843/// - If $\log_{10} x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
844/// - If $\log_{10} x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |\log_{10}
845///   x|\rfloor-p}$, where $p$ is precision of the output (typically 24 if `T` is a [`f32`] and 53
846///   if `T` is a [`f64`], but less if the output is subnormal).
847///
848/// Special cases:
849/// - $f(0)=-\infty$
850/// - $f(x)=\text{NaN}$ for $x<0$
851/// - $f(1)=0.0$
852///
853/// Neither overflow nor underflow is possible.
854///
855/// # Worst-case complexity
856/// Constant time and additional memory.
857///
858/// # Examples
859/// ```
860/// use malachite_base::num::basic::traits::{NegativeInfinity, Zero};
861/// use malachite_base::num::float::NiceFloat;
862/// use malachite_float::arithmetic::log_base_10::primitive_float_log_base_10_rational;
863/// use malachite_q::Rational;
864///
865/// assert_eq!(
866///     NiceFloat(primitive_float_log_base_10_rational::<f64>(&Rational::ZERO)),
867///     NiceFloat(f64::NEGATIVE_INFINITY)
868/// );
869/// // log_10(1000) = 3
870/// assert_eq!(
871///     NiceFloat(primitive_float_log_base_10_rational::<f64>(
872///         &Rational::from(1000)
873///     )),
874///     NiceFloat(3.0)
875/// );
876/// // log_10(1/3)
877/// assert_eq!(
878///     NiceFloat(primitive_float_log_base_10_rational::<f64>(
879///         &Rational::from_unsigneds(1u8, 3)
880///     )),
881///     NiceFloat(-0.47712125471966244)
882/// );
883/// assert_eq!(
884///     NiceFloat(primitive_float_log_base_10_rational::<f64>(
885///         &Rational::from(-1000)
886///     )),
887///     NiceFloat(f64::NAN)
888/// );
889/// ```
890#[inline]
891#[allow(clippy::type_repetition_in_bounds)]
892pub fn primitive_float_log_base_10_rational<T: PrimitiveFloat>(x: &Rational) -> T
893where
894    Float: PartialOrd<T>,
895    for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
896{
897    emulate_rational_to_float_fn(Float::log_base_10_rational_prec_ref, x)
898}