Skip to main content

malachite_float/float/arithmetic/
log_base_float_base.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};
10use crate::float::arithmetic::ln::{SliverOfOne, sliver_of_one};
11use crate::float::arithmetic::log_base::{
12    dyadic_log_of_root, dyadic_primitive_root, odd_significand_and_exponent,
13};
14use crate::float::basic::extended::ExtendedFloat;
15use crate::{
16    Float, emulate_float_float_to_float_fn, float_infinity, float_nan, float_negative_infinity,
17};
18use core::cmp::Ordering::{self, *};
19use malachite_base::num::arithmetic::traits::{CeilingLogBase2, LogBase, LogBaseAssign};
20use malachite_base::num::basic::floats::PrimitiveFloat;
21use malachite_base::num::basic::integers::PrimitiveInt;
22use malachite_base::num::basic::traits::{NegativeZero, Zero as ZeroTrait};
23use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom};
24use malachite_base::num::logic::traits::SignificantBits;
25use malachite_base::rounding_modes::RoundingMode::{self, *};
26use malachite_nz::natural::arithmetic::float_extras::float_can_round;
27use malachite_nz::platform::Limb;
28use malachite_q::Rational;
29
30// Returns `Some(log_base(x))` when it is rational, and `None` when it is irrational. The inputs `x`
31// and `base` must both be finite, positive, and not equal to 1.
32//
33// `log_base(x)` is rational exactly when `x` and `base` are commensurable (both powers of a common
34// rational). Both are dyadic, so this reuses `rational_log_base_rational_rational_base` on their
35// exact `Rational` values; for a base in (0, 1) -- where `Rational::checked_log_base` requires a
36// base above 1 -- the identity `log_b(x) = -log_{1/b}(x)` reduces to a base above 1.
37//
38// Detecting these rational results up front is essential: the Ziv loop could never certify an
39// exactly-representable one. The check is balloon-safe: it materializes `x` and `base` as
40// `Rational`s only when their exponents and precisions are within `64 * prec`.
41pub(crate) fn log_base_float_base_rational(x: &Float, base: &Float) -> Option<Rational> {
42    // Both x and the base are dyadic: the base's primitive root comes from its odd significand and
43    // exponent, and x is matched against it on its own odd significand and exponent, so neither is
44    // ever materialized as a `Rational` (their exponents may be extreme, making the integer forms
45    // enormous even though the Floats are small). No size cutoff: skipping the check when the
46    // result is exactly representable (such as `log_4` of the smallest positive Float, `-2^29`)
47    // would leave the Ziv loop unable to terminate.
48    let (s_b, t_b) = odd_significand_and_exponent(base);
49    let (z, h, e_base) = dyadic_primitive_root(&s_b, t_b);
50    let (s, t) = odd_significand_and_exponent(x);
51    let m = dyadic_log_of_root(&s, t, z, &h)?;
52    Some(Rational::from_signeds(m, i64::exact_from(e_base)))
53}
54
55// The computation of log_base(x) for a `Float` base is done by log_base(x) = log_2(x) /
56// log_2(base). The inputs are finite, positive, and not equal to 1.
57//
58// Both logarithms are ordinary, correctly-rounded `Float`s (a `Float` operand cannot be close
59// enough to 1 to make its `log_2` underflow at any practical precision), but their quotient can
60// overflow (base near 1, so `log_2(base)` is tiny) or underflow (x near 1). So the operands are
61// wrapped as `ExtendedFloat`s, divided in the extended exponent range, and converted back with a
62// single `into_float_helper` clamp. A base in (0, 1) gives a negative `log_2(base)`, so the
63// division yields the (sign-flipped) result for free.
64fn log_base_float_base_normal(
65    x: &Float,
66    base: &Float,
67    prec: u64,
68    rm: RoundingMode,
69) -> (Float, Ordering) {
70    // log_base(1) = 0, with the sign of 1 / log_2(base): positive for base > 1, negative for a base
71    // in (0, 1).
72    if *x == 1u32 {
73        return if *base < 1u32 {
74            (Float::NEGATIVE_ZERO, Equal)
75        } else {
76            (Float::ZERO, Equal)
77        };
78    }
79    // If log_base(x) is rational -- x and base commensurable -- compute it directly. This includes
80    // exactly-representable results (which the Ziv loop could never certify) as well as
81    // non-representable rationals (cheaper and exact this way).
82    if let Some(q) = log_base_float_base_rational(x, base) {
83        return Float::from_rational_prec_round(q, prec, rm);
84    }
85    // log_base(x) for x in a sliver of 1 can fall below the smallest positive Float; the 1-plus-x
86    // form handles that underflow region.
87    match sliver_of_one(x) {
88        SliverOfOne::Representable(d) => {
89            return d.log_base_float_base_1_plus_x_prec_round(base, prec, rm);
90        }
91        SliverOfOne::Underflow => {
92            return Float::log_base_rational_float_base_prec_round(
93                Rational::exact_from(x),
94                base.clone(),
95                prec,
96                rm,
97            );
98        }
99        SliverOfOne::No => {}
100    }
101    // The result is irrational, so it is never exactly representable.
102    assert_ne!(rm, Exact, "Inexact log_base_float_base");
103    // The initial slack keeps working_prec at least 7, so the working_prec - 6 below stays
104    // positive.
105    let mut working_prec = prec + 6 + prec.ceiling_log_base_2();
106    let mut increment = Limb::WIDTH;
107    loop {
108        // log_2(x) and log_2(base), correctly rounded; both finite and nonzero (x, base positive
109        // and not 1), neither underflowing, so the ordinary logs wrapped as ExtendedFloats suffice.
110        let num = ExtendedFloat::from(x.log_base_2_prec_ref(working_prec).0);
111        let den = ExtendedFloat::from(base.log_base_2_prec_ref(working_prec).0);
112        // log_2(x) / log_2(base) in the extended range; cannot overflow or underflow here.
113        let quotient = num.div_prec_val_ref(&den, working_prec).0;
114        // Two correctly-rounded logs (<= 1/2 ulp each) and the division (<= 1/2 ulp) give under 2
115        // ulps total; working_prec - 6 correct bits comfortably suffice for the rounding test.
116        if float_can_round(
117            quotient.x.significand_ref().unwrap(),
118            working_prec - 6,
119            prec,
120            rm,
121        ) {
122            // Round the mantissa to prec, then place the extended exponent, clamping once to the
123            // Float range as the rounding mode dictates.
124            let (rounded, o) = Float::from_float_prec_round(quotient.x, prec, rm);
125            let mut result = ExtendedFloat::from(rounded);
126            result.exp = result.exp.checked_add(quotient.exp).unwrap();
127            return result.into_float_helper(prec, rm, o);
128        }
129        // Increase the precision.
130        working_prec += increment;
131        increment = working_prec >> 1;
132    }
133}
134
135// Computes log_base(x) = ln(x) / ln(base) for `Float` `x` and `base`, following IEEE division of
136// the natural logs for every special case (so the function is total: no input value panics).
137fn log_base_float_base_helper(
138    x: &Float,
139    base: &Float,
140    prec: u64,
141    rm: RoundingMode,
142) -> (Float, Ordering) {
143    // ln of either operand is NaN: x or base is NaN, or (below) negative.
144    if x.is_nan() || base.is_nan() {
145        return (float_nan!(), Equal);
146    }
147    // ln(base) is NaN for a negative base (negative finite or -infinity).
148    if *base < 0u32 {
149        return (float_nan!(), Equal);
150    }
151    // ln(x) is NaN for a negative x.
152    if *x < 0u32 {
153        return (float_nan!(), Equal);
154    }
155    // x and base are each now +infinity, zero, or positive finite.
156    if base.is_infinite() {
157        // ln(base) = +infinity. ln(x) / +infinity = 0 for finite x (NaN for an infinite or zero x).
158        if x.is_infinite() || *x == 0u32 {
159            return (float_nan!(), Equal);
160        }
161        // 0, signed like ln(x): +0 for x >= 1, -0 for 0 < x < 1.
162        return if *x < 1u32 {
163            (Float::NEGATIVE_ZERO, Equal)
164        } else {
165            (Float::ZERO, Equal)
166        };
167    }
168    if *base == 0u32 {
169        // ln(base) = -infinity. ln(x) / -infinity = 0 for finite x (NaN for an infinite or zero x),
170        // sign-flipped: -0 for x >= 1, +0 for 0 < x < 1.
171        if x.is_infinite() || *x == 0u32 {
172            return (float_nan!(), Equal);
173        }
174        return if *x < 1u32 {
175            (Float::ZERO, Equal)
176        } else {
177            (Float::NEGATIVE_ZERO, Equal)
178        };
179    }
180    // base is positive finite.
181    if *base == 1u32 {
182        // ln(base) = +0. ln(x) / +0 = +-infinity by the sign of ln(x), or NaN for ln(x) = +-0.
183        if x.is_infinite() {
184            return (float_infinity!(), Equal); // ln(+inf) = +inf
185        }
186        if *x == 0u32 {
187            return (float_negative_infinity!(), Equal); // ln(0) = -inf
188        }
189        return if *x == 1u32 {
190            (float_nan!(), Equal) // +0 / +0
191        } else if *x > 1u32 {
192            (float_infinity!(), Equal)
193        } else {
194            (float_negative_infinity!(), Equal)
195        };
196    }
197    // base is positive finite and not 1.
198    if x.is_infinite() {
199        // ln(x) = +infinity. +infinity / ln(base): +infinity for base > 1, -infinity for base < 1.
200        return if *base < 1u32 {
201            (float_negative_infinity!(), Equal)
202        } else {
203            (float_infinity!(), Equal)
204        };
205    }
206    if *x == 0u32 {
207        // ln(x) = -infinity. -infinity / ln(base): -infinity for base > 1, +infinity for base < 1.
208        return if *base < 1u32 {
209            (float_infinity!(), Equal)
210        } else {
211            (float_negative_infinity!(), Equal)
212        };
213    }
214    // x and base are both positive finite, with base not 1.
215    log_base_float_base_normal(x, base, prec, rm)
216}
217
218impl Float {
219    /// Computes $\log_b x$, where $x$ and the base $b$ are both [`Float`]s, rounding the result to
220    /// the specified precision and with the specified rounding mode. The [`Float`] is taken by
221    /// value and the base by reference. An [`Ordering`] is also returned, indicating whether the
222    /// rounded value is less than, equal to, or greater than the exact value. Although `NaN`s are
223    /// not comparable to any [`Float`], whenever this function returns a `NaN` it also returns
224    /// `Equal`.
225    ///
226    /// Unlike the integer- and rational-base logarithms, the base may be any [`Float`]: the
227    /// function is defined as $\ln x / \ln b$ for every pair of [`Float`]s, applying IEEE division
228    /// to the natural logs, and never panics on an input value. In particular a base in $(0,1)$
229    /// gives a (sign-flipped) logarithm, and the non-normal and degenerate bases follow the limits
230    /// below.
231    ///
232    /// This computes $\log_2 x / \log_2 b$, wrapping both logs in an extended exponent range so
233    /// that the quotient may overflow (base near 1) or underflow (x near 1) and be clamped exactly
234    /// once.
235    ///
236    /// See [`RoundingMode`] for a description of the possible rounding modes.
237    ///
238    /// $$
239    /// f(x,b,p,m) = \log_b x+\varepsilon.
240    /// $$
241    /// - If $\log_b x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be
242    ///   0.
243    /// - If $\log_b x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
244    ///   2^{\lfloor\log_2 |\log_b x|\rfloor-p+1}$.
245    /// - If $\log_b x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
246    ///   2^{\lfloor\log_2 |\log_b x|\rfloor-p}$.
247    ///
248    /// If the output has a precision, it is `prec`.
249    ///
250    /// Special cases (with $b$ the base):
251    /// - $f(\text{NaN},b,p,m)=\text{NaN}$, and $f(x,\text{NaN},p,m)=\text{NaN}$
252    /// - $f(x,b,p,m)=\text{NaN}$ for $x<0$ or $b<0$ (including $\pm\infty$ where indicated below)
253    /// - $f(\infty,b,p,m)=\infty$ for $b>1$, and $-\infty$ for $0\leq b<1$
254    /// - $f(\pm0.0,b,p,m)=-\infty$ for $b>1$, and $\infty$ for $0<b<1$
255    /// - $f(1.0,b,p,m)=0$ (with the sign of $1/\ln b$)
256    /// - $f(x,\infty,p,m)=0$ for finite $x>0$ (and $\text{NaN}$ for $x\in\{\pm\infty,\pm0.0\}$)
257    /// - $f(x,\pm0.0,p,m)=0$ for finite $x>0$ (and $\text{NaN}$ for $x\in\{\pm\infty,\pm0.0\}$)
258    /// - $f(x,1.0,p,m)=\infty$ for $x>1$ or $x=\infty$, $-\infty$ for $0\leq x<1$, and $\text{NaN}$
259    ///   for $x=1$
260    /// - $f(g^a,g^e,p,m)=a/e$ for a common rational $g$, rounded to precision $p$; the result is
261    ///   exact if and only if $a/e$ is representable with precision $p$ (for example $\log_4
262    ///   8=3/2$)
263    ///
264    /// This function can both overflow (for a base near 1) and underflow (for an $x$ near 1).
265    ///
266    /// # Worst-case complexity
267    /// $T(n) = O(n (\log n)^2 \log\log n)$
268    ///
269    /// $M(n) = O(n (\log n)^2)$
270    ///
271    /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
272    ///
273    /// # Panics
274    /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
275    /// with the given precision.
276    ///
277    /// # Examples
278    /// ```
279    /// use malachite_base::rounding_modes::RoundingMode::*;
280    /// use malachite_float::Float;
281    /// use std::cmp::Ordering::*;
282    ///
283    /// let (log, o) = Float::from(8).log_base_float_base_prec_round(&Float::from(4), 10, Exact);
284    /// assert_eq!(log.to_string(), "1.5000"); // log_4(8) = 3/2
285    /// assert_eq!(o, Equal);
286    ///
287    /// let (log, o) = Float::from(4).log_base_float_base_prec_round(&Float::from(0.5), 10, Exact);
288    /// assert_eq!(log.to_string(), "-2.0000"); // log_{1/2}(4) = -2
289    /// assert_eq!(o, Equal);
290    /// ```
291    #[inline]
292    pub fn log_base_float_base_prec_round(
293        self,
294        base: &Self,
295        prec: u64,
296        rm: RoundingMode,
297    ) -> (Self, Ordering) {
298        assert_ne!(prec, 0);
299        log_base_float_base_helper(&self, base, prec, rm)
300    }
301
302    /// Computes $\log_b x$, where $x$ and the base $b$ are both [`Float`]s, rounding the result to
303    /// the specified precision and with the specified rounding mode. Both are taken by reference.
304    /// An [`Ordering`] is also returned, indicating whether the rounded value is less than, equal
305    /// to, or greater than the exact value.
306    ///
307    /// See [`Float::log_base_float_base_prec_round`] for details, special cases, and a description
308    /// of the rounding behavior.
309    ///
310    /// # Worst-case complexity
311    /// $T(n) = O(n (\log n)^2 \log\log n)$
312    ///
313    /// $M(n) = O(n (\log n)^2)$
314    ///
315    /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
316    ///
317    /// # Panics
318    /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
319    /// with the given precision.
320    ///
321    /// # Examples
322    /// ```
323    /// use malachite_base::rounding_modes::RoundingMode::*;
324    /// use malachite_float::Float;
325    /// use std::cmp::Ordering::*;
326    ///
327    /// let (log, o) =
328    ///     (&Float::from(8)).log_base_float_base_prec_round_ref(&Float::from(2), 10, Exact);
329    /// assert_eq!(log.to_string(), "3.0000"); // log_2(8) = 3
330    /// assert_eq!(o, Equal);
331    ///
332    /// let (log, o) =
333    ///     (&Float::from(2)).log_base_float_base_prec_round_ref(&Float::from(4), 10, Exact);
334    /// assert_eq!(log.to_string(), "0.50000"); // log_4(2) = 1/2
335    /// assert_eq!(o, Equal);
336    /// ```
337    #[inline]
338    pub fn log_base_float_base_prec_round_ref(
339        &self,
340        base: &Self,
341        prec: u64,
342        rm: RoundingMode,
343    ) -> (Self, Ordering) {
344        assert_ne!(prec, 0);
345        log_base_float_base_helper(self, base, prec, rm)
346    }
347
348    /// Computes $\log_b x$, where $x$ and the base $b$ are both [`Float`]s, rounding the result to
349    /// the nearest value of the specified precision. The [`Float`] is taken by value and the base
350    /// by reference. An [`Ordering`] is also returned.
351    ///
352    /// See [`Float::log_base_float_base_prec_round`] for details and special cases.
353    ///
354    /// # Worst-case complexity
355    /// $T(n) = O(n (\log n)^2 \log\log n)$
356    ///
357    /// $M(n) = O(n (\log n)^2)$
358    ///
359    /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
360    ///
361    /// # Panics
362    /// Panics if `prec` is zero.
363    ///
364    /// # Examples
365    /// ```
366    /// use malachite_float::Float;
367    /// use std::cmp::Ordering::*;
368    ///
369    /// let (log, o) = Float::from(8).log_base_float_base_prec(&Float::from(4), 10);
370    /// assert_eq!(log.to_string(), "1.5000"); // log_4(8) = 3/2
371    /// assert_eq!(o, Equal);
372    /// ```
373    #[inline]
374    pub fn log_base_float_base_prec(self, base: &Self, prec: u64) -> (Self, Ordering) {
375        self.log_base_float_base_prec_round(base, prec, Nearest)
376    }
377
378    /// Computes $\log_b x$, where $x$ and the base $b$ are both [`Float`]s, rounding the result to
379    /// the nearest value of the specified precision. Both are taken by reference. An [`Ordering`]
380    /// is also returned.
381    ///
382    /// See [`Float::log_base_float_base_prec_round`] for details and special cases.
383    ///
384    /// # Worst-case complexity
385    /// $T(n) = O(n (\log n)^2 \log\log n)$
386    ///
387    /// $M(n) = O(n (\log n)^2)$
388    ///
389    /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
390    ///
391    /// # Panics
392    /// Panics if `prec` is zero.
393    ///
394    /// # Examples
395    /// ```
396    /// use malachite_float::Float;
397    /// use std::cmp::Ordering::*;
398    ///
399    /// let (log, o) = (&Float::from(8)).log_base_float_base_prec_ref(&Float::from(4), 10);
400    /// assert_eq!(log.to_string(), "1.5000"); // log_4(8) = 3/2
401    /// assert_eq!(o, Equal);
402    /// ```
403    #[inline]
404    pub fn log_base_float_base_prec_ref(&self, base: &Self, prec: u64) -> (Self, Ordering) {
405        self.log_base_float_base_prec_round_ref(base, prec, Nearest)
406    }
407
408    /// Computes $\log_b x$, where $x$ and the base $b$ are both [`Float`]s, rounding the result to
409    /// the precision of the input and with the specified rounding mode. The [`Float`] is taken by
410    /// value and the base by reference. An [`Ordering`] is also returned.
411    ///
412    /// See [`Float::log_base_float_base_prec_round`] for details and special cases.
413    ///
414    /// # Worst-case complexity
415    /// $T(n) = O(n (\log n)^2 \log\log n)$
416    ///
417    /// $M(n) = O(n (\log n)^2)$
418    ///
419    /// where $T$ is time, $M$ is additional memory, and $n$ is the precision of the input.
420    ///
421    /// # Panics
422    /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input's
423    /// precision.
424    ///
425    /// # Examples
426    /// ```
427    /// use malachite_base::rounding_modes::RoundingMode::*;
428    /// use malachite_float::Float;
429    /// use std::cmp::Ordering::*;
430    ///
431    /// let (log, o) = Float::from(81).log_base_float_base_round(&Float::from(3), Exact);
432    /// assert_eq!(log.to_string(), "4.000"); // log_3(81) = 4
433    /// assert_eq!(o, Equal);
434    /// ```
435    #[inline]
436    pub fn log_base_float_base_round(self, base: &Self, rm: RoundingMode) -> (Self, Ordering) {
437        let prec = self.significant_bits();
438        self.log_base_float_base_prec_round(base, prec, rm)
439    }
440
441    /// Computes $\log_b x$, where $x$ and the base $b$ are both [`Float`]s, rounding the result to
442    /// the precision of the input and with the specified rounding mode. Both are taken by
443    /// reference. An [`Ordering`] is also returned.
444    ///
445    /// See [`Float::log_base_float_base_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    /// use std::cmp::Ordering::*;
463    ///
464    /// let (log, o) = (&Float::from(81)).log_base_float_base_round_ref(&Float::from(3), Exact);
465    /// assert_eq!(log.to_string(), "4.000"); // log_3(81) = 4
466    /// assert_eq!(o, Equal);
467    /// ```
468    #[inline]
469    pub fn log_base_float_base_round_ref(&self, base: &Self, rm: RoundingMode) -> (Self, Ordering) {
470        self.log_base_float_base_prec_round_ref(base, self.significant_bits(), rm)
471    }
472
473    /// Computes $\log_b x$, where $x$ and the base $b$ are both [`Float`]s, in place, rounding the
474    /// result to the specified precision and with the specified rounding mode. The base is taken by
475    /// reference. An [`Ordering`] is returned.
476    ///
477    /// See [`Float::log_base_float_base_prec_round`] for details and special cases.
478    ///
479    /// # Worst-case complexity
480    /// $T(n) = O(n (\log n)^2 \log\log n)$
481    ///
482    /// $M(n) = O(n (\log n)^2)$
483    ///
484    /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
485    ///
486    /// # Panics
487    /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
488    /// with the given precision.
489    ///
490    /// # Examples
491    /// ```
492    /// use malachite_base::rounding_modes::RoundingMode::*;
493    /// use malachite_float::Float;
494    /// use std::cmp::Ordering::*;
495    ///
496    /// let mut x = Float::from(8);
497    /// assert_eq!(
498    ///     x.log_base_float_base_prec_round_assign(&Float::from(4), 10, Exact),
499    ///     Equal
500    /// );
501    /// assert_eq!(x.to_string(), "1.5000"); // log_4(8) = 3/2
502    /// ```
503    #[inline]
504    pub fn log_base_float_base_prec_round_assign(
505        &mut self,
506        base: &Self,
507        prec: u64,
508        rm: RoundingMode,
509    ) -> Ordering {
510        let (result, o) = core::mem::take(self).log_base_float_base_prec_round(base, prec, rm);
511        *self = result;
512        o
513    }
514
515    /// Computes $\log_b x$, where $x$ and the base $b$ are both [`Float`]s, in place, rounding the
516    /// result to the nearest value of the specified precision. The base is taken by reference. An
517    /// [`Ordering`] is returned.
518    ///
519    /// See [`Float::log_base_float_base_prec_round`] for details and special cases.
520    ///
521    /// # Worst-case complexity
522    /// $T(n) = O(n (\log n)^2 \log\log n)$
523    ///
524    /// $M(n) = O(n (\log n)^2)$
525    ///
526    /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
527    ///
528    /// # Panics
529    /// Panics if `prec` is zero.
530    ///
531    /// # Examples
532    /// ```
533    /// use malachite_float::Float;
534    ///
535    /// let mut x = Float::from(8);
536    /// x.log_base_float_base_prec_assign(&Float::from(4), 10);
537    /// assert_eq!(x.to_string(), "1.5000"); // log_4(8) = 3/2
538    /// ```
539    #[inline]
540    pub fn log_base_float_base_prec_assign(&mut self, base: &Self, prec: u64) -> Ordering {
541        self.log_base_float_base_prec_round_assign(base, prec, Nearest)
542    }
543
544    /// Computes $\log_b x$, where $x$ and the base $b$ are both [`Float`]s, in place, rounding the
545    /// result to the precision of the input and with the specified rounding mode. The base is taken
546    /// by reference. An [`Ordering`] is returned.
547    ///
548    /// See [`Float::log_base_float_base_prec_round`] for details and special cases.
549    ///
550    /// # Worst-case complexity
551    /// $T(n) = O(n (\log n)^2 \log\log n)$
552    ///
553    /// $M(n) = O(n (\log n)^2)$
554    ///
555    /// where $T$ is time, $M$ is additional memory, and $n$ is the precision of the input.
556    ///
557    /// # Panics
558    /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input's
559    /// precision.
560    ///
561    /// # Examples
562    /// ```
563    /// use malachite_base::rounding_modes::RoundingMode::*;
564    /// use malachite_float::Float;
565    ///
566    /// let mut x = Float::from(81);
567    /// x.log_base_float_base_round_assign(&Float::from(3), Exact);
568    /// assert_eq!(x.to_string(), "4.000"); // log_3(81) = 4
569    /// ```
570    #[inline]
571    pub fn log_base_float_base_round_assign(&mut self, base: &Self, rm: RoundingMode) -> Ordering {
572        let prec = self.significant_bits();
573        self.log_base_float_base_prec_round_assign(base, prec, rm)
574    }
575}
576
577impl LogBase<Self> for Float {
578    type Output = Self;
579
580    /// Computes $\log_b x$, where $x$ and the base $b$ are both [`Float`]s, rounding the result to
581    /// the nearest value of the input's precision. Both are taken by value.
582    ///
583    /// See [`Float::log_base_float_base_prec_round`] for special cases.
584    ///
585    /// # Worst-case complexity
586    /// $T(n) = O(n (\log n)^2 \log\log n)$
587    ///
588    /// $M(n) = O(n (\log n)^2)$
589    ///
590    /// where $T$ is time, $M$ is additional memory, and $n$ is the precision of the input.
591    ///
592    /// # Examples
593    /// ```
594    /// use malachite_base::num::arithmetic::traits::LogBase;
595    /// use malachite_float::Float;
596    ///
597    /// assert_eq!(
598    ///     Float::from(81).log_base(Float::from(3)).to_string(),
599    ///     "4.000"
600    /// ); // log_3(81) = 4
601    /// assert_eq!(Float::from(9).log_base(Float::from(3)).to_string(), "2.00"); // log_3(9) = 2
602    /// ```
603    #[inline]
604    fn log_base(self, base: Self) -> Self {
605        let prec = self.significant_bits();
606        self.log_base_float_base_prec_round(&base, prec, Nearest).0
607    }
608}
609
610impl LogBase<&Float> for &Float {
611    type Output = Float;
612
613    /// Computes $\log_b x$, where $x$ and the base $b$ are both [`Float`]s, rounding the result to
614    /// the nearest value of the input's precision. Both are taken by reference.
615    ///
616    /// See [`Float::log_base_float_base_prec_round`] for special cases.
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 the precision of the input.
624    ///
625    /// # Examples
626    /// ```
627    /// use malachite_base::num::arithmetic::traits::LogBase;
628    /// use malachite_float::Float;
629    ///
630    /// assert_eq!(
631    ///     (&Float::from(81)).log_base(&Float::from(3)).to_string(),
632    ///     "4.000"
633    /// ); // log_3(81)=4
634    /// assert_eq!(
635    ///     (&Float::from(9)).log_base(&Float::from(3)).to_string(),
636    ///     "2.00"
637    /// ); // log_3(9)=2
638    /// ```
639    #[inline]
640    fn log_base(self, base: &Float) -> Float {
641        self.log_base_float_base_prec_round_ref(base, self.significant_bits(), Nearest)
642            .0
643    }
644}
645
646impl LogBaseAssign<&Self> for Float {
647    /// Replaces a [`Float`] $x$ with $\log_b x$, where the base $b$ is a [`Float`], rounding the
648    /// result to the nearest value of the input's precision. The base is taken by reference.
649    ///
650    /// See [`Float::log_base_float_base_prec_round`] for special cases.
651    ///
652    /// # Worst-case complexity
653    /// $T(n) = O(n (\log n)^2 \log\log n)$
654    ///
655    /// $M(n) = O(n (\log n)^2)$
656    ///
657    /// where $T$ is time, $M$ is additional memory, and $n$ is the precision of the input.
658    ///
659    /// # Examples
660    /// ```
661    /// use malachite_base::num::arithmetic::traits::LogBaseAssign;
662    /// use malachite_float::Float;
663    ///
664    /// let mut x = Float::from(81);
665    /// x.log_base_assign(&Float::from(3));
666    /// assert_eq!(x.to_string(), "4.000"); // log_3(81) = 4
667    /// ```
668    #[inline]
669    fn log_base_assign(&mut self, base: &Self) {
670        let prec = self.significant_bits();
671        self.log_base_float_base_prec_round_assign(base, prec, Nearest);
672    }
673}
674
675/// Computes $\log_b x$, the base-$b$ logarithm of a primitive float, where the base $b$ is also a
676/// primitive float, returning a primitive float result. Using this function is more accurate than
677/// computing the logarithm using the standard library, whose logarithm functions are not always
678/// correctly rounded.
679///
680/// Unlike the integer- and rational-base logarithms, the base may be any primitive float: the
681/// function is defined as $\ln x / \ln b$ and never panics on an input value. A base in $(0,1)$
682/// gives a (sign-flipped) logarithm, and the non-normal and degenerate bases follow the limits
683/// below.
684///
685/// $$
686/// f(x,b) = \log_b x+\varepsilon.
687/// $$
688/// - If $\log_b x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
689/// - If $\log_b x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |\log_b
690///   x|\rfloor-p}$, where $p$ is precision of the output (typically 24 if `T` is a [`f32`] and 53
691///   if `T` is a [`f64`], but less if the output is subnormal).
692///
693/// Special cases (with $b$ the base):
694/// - $f(\text{NaN},b)=\text{NaN}$, and $f(x,\text{NaN})=\text{NaN}$
695/// - $f(x,b)=\text{NaN}$ for $x<0$ or $b<0$
696/// - $f(\infty,b)=\infty$ for $b>1$, and $-\infty$ for $0\leq b<1$
697/// - $f(\pm0.0,b)=-\infty$ for $b>1$, and $\infty$ for $0<b<1$
698/// - $f(1.0,b)=0.0$ (with the sign of $1/\ln b$)
699/// - $f(x,\infty)=0.0$ for finite $x>0$ (and $\text{NaN}$ for $x\in\{\pm\infty,\pm0.0\}$)
700/// - $f(x,\pm0.0)=0.0$ for finite $x>0$ (and $\text{NaN}$ for $x\in\{\pm\infty,\pm0.0\}$)
701/// - $f(x,1.0)=\infty$ for $x>1$ or $x=\infty$, $-\infty$ for $0\leq x<1$, and $\text{NaN}$ for
702///   $x=1$
703///
704/// This function can both overflow (for a base near 1) and underflow (for an $x$ near 1).
705///
706/// # Worst-case complexity
707/// Constant time and additional memory.
708///
709/// # Examples
710/// ```
711/// use malachite_base::num::float::NiceFloat;
712/// use malachite_float::float::arithmetic::log_base_float_base::*;
713///
714/// // log_4(8) = 3/2
715/// assert_eq!(
716///     NiceFloat(primitive_float_log_base_float_base(8.0f32, 4.0)),
717///     NiceFloat(1.5)
718/// );
719/// // log_(1/2)(4) = -2
720/// assert_eq!(
721///     NiceFloat(primitive_float_log_base_float_base(4.0f32, 0.5)),
722///     NiceFloat(-2.0)
723/// );
724/// // log_10(50)
725/// assert_eq!(
726///     NiceFloat(primitive_float_log_base_float_base(50.0f32, 10.0)),
727///     NiceFloat(1.69897)
728/// );
729/// // log_inf(8) = 0
730/// assert_eq!(
731///     NiceFloat(primitive_float_log_base_float_base(8.0f32, f32::INFINITY)),
732///     NiceFloat(0.0)
733/// );
734/// assert!(primitive_float_log_base_float_base(-1.0f32, 10.0).is_nan());
735/// assert!(primitive_float_log_base_float_base(8.0f32, f32::NAN).is_nan());
736/// ```
737#[inline]
738#[allow(clippy::type_repetition_in_bounds)]
739pub fn primitive_float_log_base_float_base<T: PrimitiveFloat>(x: T, base: T) -> T
740where
741    Float: From<T> + PartialOrd<T>,
742    for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
743{
744    emulate_float_float_to_float_fn(
745        |x, base, prec| x.log_base_float_base_prec(&base, prec),
746        x,
747        base,
748    )
749}