malachite_float/float/arithmetic/log_base_10_1_plus_x.rs
1// Copyright © 2026 Mikhail Hogrefe
2//
3// This file is part of Malachite.
4//
5// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
6// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
7// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
8
9use crate::InnerFloat::{Infinity, NaN, Zero};
10use crate::float::arithmetic::log_base_1_plus_x::log_base_1_plus_x_rational;
11use crate::{Float, emulate_float_to_float_fn, float_infinity, float_nan, float_negative_infinity};
12use core::cmp::Ordering::{self, *};
13use malachite_base::num::arithmetic::traits::{
14 CeilingLogBase2, LogBase10Of1PlusX, LogBase10Of1PlusXAssign,
15};
16use malachite_base::num::basic::floats::PrimitiveFloat;
17use malachite_base::num::basic::integers::PrimitiveInt;
18use malachite_base::num::comparison::traits::PartialOrdAbs;
19use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom};
20use malachite_base::num::logic::traits::SignificantBits;
21use malachite_base::rounding_modes::RoundingMode::{self, *};
22use malachite_nz::natural::arithmetic::float::round::float_can_round;
23use malachite_nz::platform::Limb;
24
25// The computation of log_base_10_1_plus_x(x) is done by log_10(1 + x) = log_2(1 + x) / log_2(10).
26// The input is finite and greater than -1.
27//
28// This specializes `log_base_1_plus_x` to base 10. Like that function (and unlike the plain
29// `log_base_10`), it routes through `log_base_2_1_plus_x` rather than computing `log_10(1 + x)`
30// from `1 + x` directly, preserving accuracy when x is near 0 where `1 + x` would lose precision.
31// Since 10 = 2 * 5 is not a perfect power, `log_10(1 + x)` is rational only when `1 + x = 10^m` (m
32// a nonnegative integer, so x = 0 or x = 10^m - 1); those exact results are detected up front (the
33// Ziv loop could never certify an exactly-representable one). `log_2(10)` is irrational, so every
34// other result is strictly between `Float`s and the loop converges.
35fn log_base_10_1_plus_x_prec_round_normal(
36 x: &Float,
37 prec: u64,
38 rm: RoundingMode,
39) -> (Float, Ordering) {
40 // log_10(1 + x) is undefined for x < -1.
41 match x.partial_cmp(&-1i32).unwrap() {
42 // 1 + x = 0, so log_10(1 + x) = -infinity.
43 Equal => return (float_negative_infinity!(), Equal),
44 Less => return (float_nan!(), Equal),
45 _ => {}
46 }
47 // If 1 + x = 10^m, then log_10(1 + x) = m is rational and exact. `log_base_1_plus_x_rational`
48 // with base 10 returns `Some(m / 1)`.
49 if let Some(q) = log_base_1_plus_x_rational(x, 10) {
50 return Float::from_rational_prec_round(q, prec, rm);
51 }
52 // The result is irrational, so it is never exactly representable.
53 assert_ne!(rm, Exact, "Inexact log_base_10_1_plus_x");
54 const TEN: Float = Float::const_from_unsigned(10);
55 let min_exp = Float::MIN_EXPONENT_I64;
56 let mut working_prec = prec + 4 + prec.ceiling_log_base_2();
57 let mut increment = Limb::WIDTH;
58 loop {
59 // log_2(1 + x), correctly rounded to working_prec; always within the Float exponent range.
60 let num = x.log_base_2_1_plus_x_prec_ref(working_prec).0;
61 // log_2(10) > 1, correctly rounded to working_prec.
62 let den = TEN.log_base_2_prec(working_prec).0;
63 // Dividing by log_2(10) > 1 only shrinks the magnitude (overflow is impossible), but can
64 // push the result below MIN_EXPONENT. When it underflows, the Ziv test below could never
65 // resolve it (the quotient clamps), so hand the rounding to div_prec_round, which clamps to
66 // zero or the minimum positive value per the rounding mode. The exact quotient exponent is
67 // only resolved in the narrow band where the cheap exponent bound is inconclusive (then
68 // e_num - e_den == min_exp - 1, so the result underflows iff |log_2(1 + x)| * 2^(1 -
69 // min_exp) < log_2(10)). The left shift only adjusts the exponent, avoiding a huge Rational
70 // conversion.
71 let e_num = i64::from(num.get_exponent().unwrap());
72 let e_den = i64::from(den.get_exponent().unwrap());
73 if e_num - e_den + 1 < min_exp
74 || (e_num - e_den < min_exp && (&num << u64::exact_from(1 - min_exp)).lt_abs(&den))
75 {
76 return num.div_prec_round(den, prec, rm);
77 }
78 // log_2(1 + x) / log_2(10), with three correctly-rounded operations (log_base_2_1_plus_x,
79 // log_base_2, and the division, each at most 1/2 ulp), so the relative error is below 2^(2
80 // - working_prec) and working_prec - 4 correct bits suffice for rounding.
81 let t = num / den;
82 if float_can_round(t.significand_ref().unwrap(), working_prec - 4, prec, rm) {
83 return Float::from_float_prec_round(t, prec, rm);
84 }
85 // Increase the precision.
86 working_prec += increment;
87 increment = working_prec >> 1;
88 }
89}
90
91impl Float {
92 /// Computes $\log_{10}(1+x)$, where $x$ is a [`Float`], rounding the result to the specified
93 /// precision and with the specified rounding mode. The [`Float`] is taken by value. An
94 /// [`Ordering`] is also returned, indicating whether the rounded value is less than, equal to,
95 /// or greater than the exact value. Although `NaN`s are not comparable to any [`Float`],
96 /// whenever this function returns a `NaN` it also returns `Equal`.
97 ///
98 /// $\log_{10}(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, `NaN` is returned.
99 ///
100 /// This computes $\log_2(1+x) / \log_2 10$, preserving accuracy for $x$ near 0.
101 ///
102 /// See [`RoundingMode`] for a description of the possible rounding modes.
103 ///
104 /// $$
105 /// f(x,p,m) = \log_{10}(1+x)+\varepsilon.
106 /// $$
107 /// - If $\log_{10}(1+x)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
108 /// to be 0.
109 /// - If $\log_{10}(1+x)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
110 /// 2^{\lfloor\log_2 |\log_{10}(1+x)|\rfloor-p+1}$.
111 /// - If $\log_{10}(1+x)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
112 /// 2^{\lfloor\log_2 |\log_{10}(1+x)|\rfloor-p}$.
113 ///
114 /// If the output has a precision, it is `prec`.
115 ///
116 /// Special cases:
117 /// - $f(\text{NaN},p,m)=\text{NaN}$
118 /// - $f(\infty,p,m)=\infty$
119 /// - $f(-\infty,p,m)=\text{NaN}$
120 /// - $f(\pm0.0,p,m)=\pm0.0$
121 /// - $f(-1.0,p,m)=-\infty$
122 /// - $f(x,p,m)=\text{NaN}$ for $x<-1$
123 /// - $f(x,p,m)=m$ when $1+x=10^m$, rounded to precision $p$; the result is exact if and only if
124 /// $m$ is representable with precision $p$ (for example $\log_{10}(1+9)=1$ when $x=9$ is
125 /// exact)
126 ///
127 /// This function cannot overflow, but it can underflow.
128 ///
129 /// If you know you'll be using `Nearest`, consider using [`Float::log_base_10_1_plus_x_prec`]
130 /// instead. If you know that your target precision is the precision of the input, consider
131 /// using [`Float::log_base_10_1_plus_x_round`] instead. If both of these things are true,
132 /// consider using `(&Float).log_base_10_1_plus_x()` instead.
133 ///
134 /// # Worst-case complexity
135 /// $T(n, m) = O(n (\log n)^2 \log\log n + m \log m \log\log m)$
136 ///
137 /// $M(n, m) = O(n \log n + m \log m)$
138 ///
139 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
140 /// `self.significant_bits()`.
141 ///
142 /// # Panics
143 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
144 /// with the given precision.
145 ///
146 /// # Examples
147 /// ```
148 /// use malachite_base::num::basic::traits::One;
149 /// use malachite_base::rounding_modes::RoundingMode::*;
150 /// use malachite_float::Float;
151 /// use std::cmp::Ordering::*;
152 ///
153 /// let (log, o) = Float::from(9).log_base_10_1_plus_x_prec_round(10, Exact);
154 /// assert_eq!(log.to_string(), "1.0000"); // log_10(10) = 1
155 /// assert_eq!(o, Equal);
156 ///
157 /// let (log, o) = Float::ONE.log_base_10_1_plus_x_prec_round(20, Nearest);
158 /// assert_eq!(log.to_string(), "0.30103016"); // log_10(2)
159 /// assert_eq!(o, Greater);
160 /// ```
161 #[inline]
162 pub fn log_base_10_1_plus_x_prec_round(self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
163 assert_ne!(prec, 0);
164 match self {
165 Self(NaN | Infinity { sign: false }) => (float_nan!(), Equal),
166 float_infinity!() => (float_infinity!(), Equal),
167 Self(Zero { .. }) => (self, Equal),
168 _ => log_base_10_1_plus_x_prec_round_normal(&self, prec, rm),
169 }
170 }
171
172 /// Computes $\log_{10}(1+x)$, where $x$ is a [`Float`], rounding the result to the specified
173 /// precision and with the specified rounding mode. The [`Float`] is taken by reference. An
174 /// [`Ordering`] is also returned, indicating whether the rounded value is less than, equal to,
175 /// or greater than the exact value. Although `NaN`s are not comparable to any [`Float`],
176 /// whenever this function returns a `NaN` it also returns `Equal`.
177 ///
178 /// See [`Float::log_base_10_1_plus_x_prec_round`] for details, special cases, and a description
179 /// of the rounding behavior.
180 ///
181 /// # Worst-case complexity
182 /// $T(n, m) = O(n (\log n)^2 \log\log n + m \log m \log\log m)$
183 ///
184 /// $M(n, m) = O(n \log n + m \log m)$
185 ///
186 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
187 /// `self.significant_bits()`.
188 ///
189 /// # Panics
190 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
191 /// with the given precision.
192 ///
193 /// # Examples
194 /// ```
195 /// use malachite_base::num::basic::traits::One;
196 /// use malachite_base::rounding_modes::RoundingMode::*;
197 /// use malachite_float::Float;
198 /// use std::cmp::Ordering::*;
199 ///
200 /// let (log, o) = (&Float::from(99)).log_base_10_1_plus_x_prec_round_ref(10, Exact);
201 /// assert_eq!(log.to_string(), "2.0000"); // log_10(100) = 2
202 /// assert_eq!(o, Equal);
203 ///
204 /// let (log, o) = (&Float::ONE).log_base_10_1_plus_x_prec_round_ref(20, Floor);
205 /// assert_eq!(log.to_string(), "0.30102968"); // log_10(2), rounded down
206 /// assert_eq!(o, Less);
207 /// ```
208 #[inline]
209 pub fn log_base_10_1_plus_x_prec_round_ref(
210 &self,
211 prec: u64,
212 rm: RoundingMode,
213 ) -> (Self, Ordering) {
214 assert_ne!(prec, 0);
215 match self {
216 Self(NaN | Infinity { sign: false }) => (float_nan!(), Equal),
217 float_infinity!() => (float_infinity!(), Equal),
218 Self(Zero { .. }) => (self.clone(), Equal),
219 _ => log_base_10_1_plus_x_prec_round_normal(self, prec, rm),
220 }
221 }
222
223 /// Computes $\log_{10}(1+x)$, where $x$ is a [`Float`], rounding the result to the nearest
224 /// value of the specified precision. The [`Float`] is taken by value. An [`Ordering`] is also
225 /// returned, indicating whether the rounded value is less than, equal to, or greater than the
226 /// exact value.
227 ///
228 /// See [`Float::log_base_10_1_plus_x_prec_round`] for details and special cases.
229 ///
230 /// # Worst-case complexity
231 /// $T(n, m) = O(n (\log n)^2 \log\log n + m \log m \log\log m)$
232 ///
233 /// $M(n, m) = O(n \log n + m \log m)$
234 ///
235 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
236 /// `self.significant_bits()`.
237 ///
238 /// # Panics
239 /// Panics if `prec` is zero.
240 ///
241 /// # Examples
242 /// ```
243 /// use malachite_base::num::basic::traits::One;
244 /// use malachite_float::Float;
245 /// use std::cmp::Ordering::*;
246 ///
247 /// let (log, o) = Float::from(9).log_base_10_1_plus_x_prec(10);
248 /// assert_eq!(log.to_string(), "1.0000"); // log_10(10) = 1
249 /// assert_eq!(o, Equal);
250 ///
251 /// let (log, o) = Float::ONE.log_base_10_1_plus_x_prec(20);
252 /// assert_eq!(log.to_string(), "0.30103016"); // log_10(2)
253 /// assert_eq!(o, Greater);
254 /// ```
255 #[inline]
256 pub fn log_base_10_1_plus_x_prec(self, prec: u64) -> (Self, Ordering) {
257 self.log_base_10_1_plus_x_prec_round(prec, Nearest)
258 }
259
260 /// Computes $\log_{10}(1+x)$, where $x$ is a [`Float`], rounding the result to the nearest
261 /// value of the specified precision. The [`Float`] is taken by reference. An [`Ordering`] is
262 /// also returned, indicating whether the rounded value is less than, equal to, or greater than
263 /// the exact value.
264 ///
265 /// See [`Float::log_base_10_1_plus_x_prec_round`] for details and special cases.
266 ///
267 /// # Worst-case complexity
268 /// $T(n, m) = O(n (\log n)^2 \log\log n + m \log m \log\log m)$
269 ///
270 /// $M(n, m) = O(n \log n + m \log m)$
271 ///
272 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
273 /// `self.significant_bits()`.
274 ///
275 /// # Panics
276 /// Panics if `prec` is zero.
277 ///
278 /// # Examples
279 /// ```
280 /// use malachite_float::Float;
281 /// use std::cmp::Ordering::*;
282 ///
283 /// let (log, o) = (&Float::from(99)).log_base_10_1_plus_x_prec_ref(10);
284 /// assert_eq!(log.to_string(), "2.0000"); // log_10(100) = 2
285 /// assert_eq!(o, Equal);
286 ///
287 /// let (log, o) = (&Float::from(7)).log_base_10_1_plus_x_prec_ref(30);
288 /// assert_eq!(log.to_string(), "0.90308998711"); // log_10(8)
289 /// assert_eq!(o, Greater);
290 /// ```
291 #[inline]
292 pub fn log_base_10_1_plus_x_prec_ref(&self, prec: u64) -> (Self, Ordering) {
293 self.log_base_10_1_plus_x_prec_round_ref(prec, Nearest)
294 }
295
296 /// Computes $\log_{10}(1+x)$, where $x$ is a [`Float`], rounding the result to the precision of
297 /// the input and with the specified rounding mode. The [`Float`] is taken by value. An
298 /// [`Ordering`] is also returned, indicating whether the rounded value is less than, equal to,
299 /// or greater than the exact value.
300 ///
301 /// See [`Float::log_base_10_1_plus_x_prec_round`] for details and special cases.
302 ///
303 /// # Worst-case complexity
304 /// $T(n) = O(n (\log n)^2 \log\log n)$
305 ///
306 /// $M(n) = O(n \log n)$
307 ///
308 /// where $T$ is time, $M$ is additional memory, and $n$ is the precision of the input.
309 ///
310 /// # Panics
311 /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input's
312 /// precision.
313 ///
314 /// # Examples
315 /// ```
316 /// use malachite_base::rounding_modes::RoundingMode::*;
317 /// use malachite_float::Float;
318 /// use std::cmp::Ordering::*;
319 ///
320 /// let (log, o) = Float::from(9).log_base_10_1_plus_x_round(Exact);
321 /// assert_eq!(log.to_string(), "1.00"); // log_10(10) = 1
322 /// assert_eq!(o, Equal);
323 ///
324 /// let (log, o) = Float::from(99).log_base_10_1_plus_x_round(Exact);
325 /// assert_eq!(log.to_string(), "2.000"); // log_10(100) = 2
326 /// assert_eq!(o, Equal);
327 /// ```
328 #[inline]
329 pub fn log_base_10_1_plus_x_round(self, rm: RoundingMode) -> (Self, Ordering) {
330 let prec = self.significant_bits();
331 self.log_base_10_1_plus_x_prec_round(prec, rm)
332 }
333
334 /// Computes $\log_{10}(1+x)$, where $x$ is a [`Float`], rounding the result to the precision of
335 /// the input and with the specified rounding mode. The [`Float`] is taken by reference. An
336 /// [`Ordering`] is also returned, indicating whether the rounded value is less than, equal to,
337 /// or greater than the exact value.
338 ///
339 /// See [`Float::log_base_10_1_plus_x_prec_round`] for details and special cases.
340 ///
341 /// # Worst-case complexity
342 /// $T(n) = O(n (\log n)^2 \log\log n)$
343 ///
344 /// $M(n) = O(n \log n)$
345 ///
346 /// where $T$ is time, $M$ is additional memory, and $n$ is the precision of the input.
347 ///
348 /// # Panics
349 /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input's
350 /// precision.
351 ///
352 /// # Examples
353 /// ```
354 /// use malachite_base::rounding_modes::RoundingMode::*;
355 /// use malachite_float::Float;
356 /// use std::cmp::Ordering::*;
357 ///
358 /// let (log, o) = (&Float::from(99)).log_base_10_1_plus_x_round_ref(Exact);
359 /// assert_eq!(log.to_string(), "2.000"); // log_10(100) = 2
360 /// assert_eq!(o, Equal);
361 ///
362 /// let (log, o) = (&Float::from(9)).log_base_10_1_plus_x_round_ref(Exact);
363 /// assert_eq!(log.to_string(), "1.00"); // log_10(10) = 1
364 /// assert_eq!(o, Equal);
365 /// ```
366 #[inline]
367 pub fn log_base_10_1_plus_x_round_ref(&self, rm: RoundingMode) -> (Self, Ordering) {
368 self.log_base_10_1_plus_x_prec_round_ref(self.significant_bits(), rm)
369 }
370
371 /// Computes $\log_{10}(1+x)$, where $x$ is a [`Float`], in place, rounding the result to the
372 /// specified precision and with the specified rounding mode. An [`Ordering`] is returned,
373 /// indicating whether the rounded value is less than, equal to, or greater than the exact
374 /// value.
375 ///
376 /// See [`Float::log_base_10_1_plus_x_prec_round`] for details and special cases.
377 ///
378 /// # Worst-case complexity
379 /// $T(n, m) = O(n (\log n)^2 \log\log n + m \log m \log\log m)$
380 ///
381 /// $M(n, m) = O(n \log n + m \log m)$
382 ///
383 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
384 /// `self.significant_bits()`.
385 ///
386 /// # Panics
387 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
388 /// with the given precision.
389 ///
390 /// # Examples
391 /// ```
392 /// use malachite_base::num::basic::traits::One;
393 /// use malachite_base::rounding_modes::RoundingMode::*;
394 /// use malachite_float::Float;
395 /// use std::cmp::Ordering::*;
396 ///
397 /// let mut x = Float::from(9);
398 /// assert_eq!(x.log_base_10_1_plus_x_prec_round_assign(10, Exact), Equal);
399 /// assert_eq!(x.to_string(), "1.0000"); // log_10(10) = 1
400 ///
401 /// let mut x = Float::ONE;
402 /// assert_eq!(x.log_base_10_1_plus_x_prec_round_assign(20, Floor), Less);
403 /// assert_eq!(x.to_string(), "0.30102968"); // log_10(2), rounded down
404 /// ```
405 #[inline]
406 pub fn log_base_10_1_plus_x_prec_round_assign(
407 &mut self,
408 prec: u64,
409 rm: RoundingMode,
410 ) -> Ordering {
411 let (result, o) = core::mem::take(self).log_base_10_1_plus_x_prec_round(prec, rm);
412 *self = result;
413 o
414 }
415
416 /// Computes $\log_{10}(1+x)$, where $x$ is a [`Float`], in place, rounding the result to the
417 /// nearest value of the specified precision. An [`Ordering`] is returned, indicating whether
418 /// the rounded value is less than, equal to, or greater than the exact value.
419 ///
420 /// See [`Float::log_base_10_1_plus_x_prec_round`] for details and special cases.
421 ///
422 /// # Worst-case complexity
423 /// $T(n, m) = O(n (\log n)^2 \log\log n + m \log m \log\log m)$
424 ///
425 /// $M(n, m) = O(n \log n + m \log m)$
426 ///
427 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
428 /// `self.significant_bits()`.
429 ///
430 /// # Panics
431 /// Panics if `prec` is zero.
432 ///
433 /// # Examples
434 /// ```
435 /// use malachite_float::Float;
436 ///
437 /// let mut x = Float::from(9);
438 /// x.log_base_10_1_plus_x_prec_assign(10);
439 /// assert_eq!(x.to_string(), "1.0000"); // log_10(10) = 1
440 ///
441 /// let mut x = Float::from(99);
442 /// x.log_base_10_1_plus_x_prec_assign(10);
443 /// assert_eq!(x.to_string(), "2.0000"); // log_10(100) = 2
444 /// ```
445 #[inline]
446 pub fn log_base_10_1_plus_x_prec_assign(&mut self, prec: u64) -> Ordering {
447 self.log_base_10_1_plus_x_prec_round_assign(prec, Nearest)
448 }
449
450 /// Computes $\log_{10}(1+x)$, where $x$ is a [`Float`], in place, rounding the result to the
451 /// precision of the input and with the specified rounding mode. An [`Ordering`] is returned,
452 /// indicating whether the rounded value is less than, equal to, or greater than the exact
453 /// value.
454 ///
455 /// See [`Float::log_base_10_1_plus_x_prec_round`] for details and special cases.
456 ///
457 /// # Worst-case complexity
458 /// $T(n) = O(n (\log n)^2 \log\log n)$
459 ///
460 /// $M(n) = O(n \log n)$
461 ///
462 /// where $T$ is time, $M$ is additional memory, and $n$ is the precision of the input.
463 ///
464 /// # Panics
465 /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input's
466 /// precision.
467 ///
468 /// # Examples
469 /// ```
470 /// use malachite_base::rounding_modes::RoundingMode::*;
471 /// use malachite_float::Float;
472 ///
473 /// let mut x = Float::from(9);
474 /// x.log_base_10_1_plus_x_round_assign(Exact);
475 /// assert_eq!(x.to_string(), "1.00"); // log_10(10) = 1
476 ///
477 /// let mut x = Float::from(99);
478 /// x.log_base_10_1_plus_x_round_assign(Exact);
479 /// assert_eq!(x.to_string(), "2.000"); // log_10(100) = 2
480 /// ```
481 #[inline]
482 pub fn log_base_10_1_plus_x_round_assign(&mut self, rm: RoundingMode) -> Ordering {
483 let prec = self.significant_bits();
484 self.log_base_10_1_plus_x_prec_round_assign(prec, rm)
485 }
486}
487
488impl LogBase10Of1PlusX for Float {
489 type Output = Self;
490
491 /// Computes $\log_{10}(1+x)$, where $x$ is a [`Float`], rounding the result to the nearest
492 /// value of the input's precision. The [`Float`] is taken by value.
493 ///
494 /// $\log_{10}(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, `NaN` is returned. See
495 /// [`Float::log_base_10_1_plus_x_prec_round`] for the other special cases.
496 ///
497 /// # Worst-case complexity
498 /// $T(n) = O(n (\log n)^2 \log\log n)$
499 ///
500 /// $M(n) = O(n \log n)$
501 ///
502 /// where $T$ is time, $M$ is additional memory, and $n$ is the precision of the input.
503 ///
504 /// # Examples
505 /// ```
506 /// use malachite_base::num::arithmetic::traits::LogBase10Of1PlusX;
507 /// use malachite_float::Float;
508 ///
509 /// assert_eq!(Float::from(9).log_base_10_1_plus_x().to_string(), "1.00"); // log_10(10) = 1
510 /// assert_eq!(Float::from(99).log_base_10_1_plus_x().to_string(), "2.000"); // log_10(100) = 2
511 /// ```
512 #[inline]
513 fn log_base_10_1_plus_x(self) -> Self {
514 let prec = self.significant_bits();
515 self.log_base_10_1_plus_x_prec_round(prec, Nearest).0
516 }
517}
518
519impl LogBase10Of1PlusX for &Float {
520 type Output = Float;
521
522 /// Computes $\log_{10}(1+x)$, where $x$ is a [`Float`], rounding the result to the nearest
523 /// value of the input's precision. The [`Float`] is taken by reference.
524 ///
525 /// $\log_{10}(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, `NaN` is returned. See
526 /// [`Float::log_base_10_1_plus_x_prec_round`] for the other special cases.
527 ///
528 /// # Worst-case complexity
529 /// $T(n) = O(n (\log n)^2 \log\log n)$
530 ///
531 /// $M(n) = O(n \log n)$
532 ///
533 /// where $T$ is time, $M$ is additional memory, and $n$ is the precision of the input.
534 ///
535 /// # Examples
536 /// ```
537 /// use malachite_base::num::arithmetic::traits::LogBase10Of1PlusX;
538 /// use malachite_float::Float;
539 ///
540 /// assert_eq!((&Float::from(9)).log_base_10_1_plus_x().to_string(), "1.00"); // log_10(10) = 1
541 /// assert_eq!(
542 /// (&Float::from(99)).log_base_10_1_plus_x().to_string(),
543 /// "2.000"
544 /// ); // log_10(100) = 2
545 /// ```
546 #[inline]
547 fn log_base_10_1_plus_x(self) -> Float {
548 self.log_base_10_1_plus_x_prec_round_ref(self.significant_bits(), Nearest)
549 .0
550 }
551}
552
553impl LogBase10Of1PlusXAssign for Float {
554 /// Replaces a [`Float`] $x$ with $\log_{10}(1+x)$, rounding the result to the nearest value of
555 /// the input's precision.
556 ///
557 /// $\log_{10}(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, `NaN` is returned. See
558 /// [`Float::log_base_10_1_plus_x_prec_round`] for the other special cases.
559 ///
560 /// # Worst-case complexity
561 /// $T(n) = O(n (\log n)^2 \log\log n)$
562 ///
563 /// $M(n) = O(n \log n)$
564 ///
565 /// where $T$ is time, $M$ is additional memory, and $n$ is the precision of the input.
566 ///
567 /// # Examples
568 /// ```
569 /// use malachite_base::num::arithmetic::traits::LogBase10Of1PlusXAssign;
570 /// use malachite_float::Float;
571 ///
572 /// let mut x = Float::from(9);
573 /// x.log_base_10_1_plus_x_assign();
574 /// assert_eq!(x.to_string(), "1.00"); // log_10(10) = 1
575 ///
576 /// let mut x = Float::from(99);
577 /// x.log_base_10_1_plus_x_assign();
578 /// assert_eq!(x.to_string(), "2.000"); // log_10(100) = 2
579 /// ```
580 #[inline]
581 fn log_base_10_1_plus_x_assign(&mut self) {
582 let prec = self.significant_bits();
583 self.log_base_10_1_plus_x_prec_round_assign(prec, Nearest);
584 }
585}
586
587/// Computes $\log_{10}(1+x)$, the base-10 logarithm of one plus a primitive float. Using this
588/// function is more accurate than computing `(1 + x).log10()`, both because $1+x$ may not be
589/// representable as a primitive float and because the standard library's `log10` is not always
590/// correctly rounded.
591///
592/// $\log_{10}(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, `NaN` is returned.
593///
594/// $$
595/// f(x) = \log_{10}(1+x)+\varepsilon.
596/// $$
597/// - If $\log_{10}(1+x)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be
598/// 0.
599/// - If $\log_{10}(1+x)$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2
600/// |\log_{10}(1+x)|\rfloor-p}$, where $p$ is precision of the output (typically 24 if `T` is a
601/// [`f32`] and 53 if `T` is a [`f64`], but less if the output is subnormal).
602///
603/// Special cases:
604/// - $f(\text{NaN})=\text{NaN}$
605/// - $f(\infty)=\infty$
606/// - $f(-\infty)=\text{NaN}$
607/// - $f(\pm0.0)=\pm0.0$
608/// - $f(-1.0)=-\infty$
609/// - $f(x)=\text{NaN}$ for $x<-1$
610///
611/// This function can underflow (to a subnormal or zero) when $x$ is close to zero, but it cannot
612/// overflow.
613///
614/// # Worst-case complexity
615/// Constant time and additional memory.
616///
617/// # Examples
618/// ```
619/// use malachite_base::num::basic::traits::NegativeInfinity;
620/// use malachite_base::num::float::NiceFloat;
621/// use malachite_float::float::arithmetic::log_base_10_1_plus_x::*;
622///
623/// assert!(primitive_float_log_base_10_1_plus_x(f32::NAN).is_nan());
624/// assert_eq!(
625/// NiceFloat(primitive_float_log_base_10_1_plus_x(f32::INFINITY)),
626/// NiceFloat(f32::INFINITY)
627/// );
628/// assert_eq!(
629/// NiceFloat(primitive_float_log_base_10_1_plus_x(-1.0f32)),
630/// NiceFloat(f32::NEGATIVE_INFINITY)
631/// );
632/// assert!(primitive_float_log_base_10_1_plus_x(-2.0f32).is_nan());
633/// // log_10(1 + 999) = log_10(1000) = 3
634/// assert_eq!(
635/// NiceFloat(primitive_float_log_base_10_1_plus_x(999.0f32)),
636/// NiceFloat(3.0)
637/// );
638/// // log_10(1 + 9) = log_10(10) = 1
639/// assert_eq!(
640/// NiceFloat(primitive_float_log_base_10_1_plus_x(9.0f32)),
641/// NiceFloat(1.0)
642/// );
643/// // log_10(1 + 1) = log_10(2)
644/// assert_eq!(
645/// NiceFloat(primitive_float_log_base_10_1_plus_x(1.0f32)),
646/// NiceFloat(std::f32::consts::LOG10_2)
647/// );
648/// ```
649#[inline]
650#[allow(clippy::type_repetition_in_bounds)]
651pub fn primitive_float_log_base_10_1_plus_x<T: PrimitiveFloat>(x: T) -> T
652where
653 Float: From<T> + PartialOrd<T>,
654 for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
655{
656 emulate_float_to_float_fn(Float::log_base_10_1_plus_x_prec, x)
657}