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