Skip to main content

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