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