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}