malachite_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::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_extras::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 = i64::from(Float::MIN_EXPONENT);
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_ref(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.div_prec(den, working_prec).0;
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) = O(n (\log n)^2 \log\log n)$
136 ///
137 /// $M(n) = O(n (\log n)^2)$
138 ///
139 /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
140 ///
141 /// # Panics
142 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
143 /// with the given precision.
144 ///
145 /// # Examples
146 /// ```
147 /// use malachite_base::rounding_modes::RoundingMode::*;
148 /// use malachite_float::Float;
149 /// use std::cmp::Ordering::*;
150 ///
151 /// let (log, o) = Float::from(9).log_base_10_1_plus_x_prec_round(10, Exact);
152 /// assert_eq!(log.to_string(), "1.0"); // log_10(10) = 1
153 /// assert_eq!(o, Equal);
154 ///
155 /// let (log, o) = Float::from(1).log_base_10_1_plus_x_prec_round(20, Nearest);
156 /// assert_eq!(log.to_string(), "0.3010302"); // log_10(2)
157 /// assert_eq!(o, Greater);
158 /// ```
159 #[inline]
160 pub fn log_base_10_1_plus_x_prec_round(self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
161 assert_ne!(prec, 0);
162 match self {
163 Self(NaN | Infinity { sign: false }) => (float_nan!(), Equal),
164 float_infinity!() => (float_infinity!(), Equal),
165 Self(Zero { .. }) => (self, Equal),
166 _ => log_base_10_1_plus_x_prec_round_normal(&self, prec, rm),
167 }
168 }
169
170 /// Computes $\log_{10}(1+x)$, where $x$ is a [`Float`], rounding the result to the specified
171 /// precision and with the specified rounding mode. The [`Float`] is taken by reference. An
172 /// [`Ordering`] is also returned, indicating whether the rounded value is less than, equal to,
173 /// or greater than the exact value. Although `NaN`s are not comparable to any [`Float`],
174 /// whenever this function returns a `NaN` it also returns `Equal`.
175 ///
176 /// See [`Float::log_base_10_1_plus_x_prec_round`] for details, special cases, and a description
177 /// of the rounding behavior.
178 ///
179 /// # Worst-case complexity
180 /// $T(n) = O(n (\log n)^2 \log\log n)$
181 ///
182 /// $M(n) = O(n (\log n)^2)$
183 ///
184 /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
185 ///
186 /// # Panics
187 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
188 /// with the given precision.
189 ///
190 /// # Examples
191 /// ```
192 /// use malachite_base::rounding_modes::RoundingMode::*;
193 /// use malachite_float::Float;
194 /// use std::cmp::Ordering::*;
195 ///
196 /// let (log, o) = (&Float::from(99)).log_base_10_1_plus_x_prec_round_ref(10, Exact);
197 /// assert_eq!(log.to_string(), "2.0"); // log_10(100) = 2
198 /// assert_eq!(o, Equal);
199 ///
200 /// let (log, o) = (&Float::from(1)).log_base_10_1_plus_x_prec_round_ref(20, Floor);
201 /// assert_eq!(log.to_string(), "0.3010297"); // log_10(2), rounded down
202 /// assert_eq!(o, Less);
203 /// ```
204 #[inline]
205 pub fn log_base_10_1_plus_x_prec_round_ref(
206 &self,
207 prec: u64,
208 rm: RoundingMode,
209 ) -> (Self, Ordering) {
210 assert_ne!(prec, 0);
211 match self {
212 Self(NaN | Infinity { sign: false }) => (float_nan!(), Equal),
213 float_infinity!() => (float_infinity!(), Equal),
214 Self(Zero { .. }) => (self.clone(), Equal),
215 _ => log_base_10_1_plus_x_prec_round_normal(self, prec, rm),
216 }
217 }
218
219 /// Computes $\log_{10}(1+x)$, where $x$ is a [`Float`], rounding the result to the nearest
220 /// value of the specified precision. The [`Float`] is taken by value. An [`Ordering`] is also
221 /// returned, indicating whether the rounded value is less than, equal to, or greater than the
222 /// exact value.
223 ///
224 /// See [`Float::log_base_10_1_plus_x_prec_round`] for details and special cases.
225 ///
226 /// # Worst-case complexity
227 /// $T(n) = O(n (\log n)^2 \log\log n)$
228 ///
229 /// $M(n) = O(n (\log n)^2)$
230 ///
231 /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
232 ///
233 /// # Panics
234 /// Panics if `prec` is zero.
235 ///
236 /// # Examples
237 /// ```
238 /// use malachite_float::Float;
239 /// use std::cmp::Ordering::*;
240 ///
241 /// let (log, o) = Float::from(9).log_base_10_1_plus_x_prec(10);
242 /// assert_eq!(log.to_string(), "1.0"); // log_10(10) = 1
243 /// assert_eq!(o, Equal);
244 ///
245 /// let (log, o) = Float::from(1).log_base_10_1_plus_x_prec(20);
246 /// assert_eq!(log.to_string(), "0.3010302"); // log_10(2)
247 /// assert_eq!(o, Greater);
248 /// ```
249 #[inline]
250 pub fn log_base_10_1_plus_x_prec(self, prec: u64) -> (Self, Ordering) {
251 self.log_base_10_1_plus_x_prec_round(prec, Nearest)
252 }
253
254 /// Computes $\log_{10}(1+x)$, where $x$ is a [`Float`], rounding the result to the nearest
255 /// value of the specified precision. The [`Float`] is taken by reference. An [`Ordering`] is
256 /// also returned, indicating whether the rounded value is less than, equal to, or greater than
257 /// the exact value.
258 ///
259 /// See [`Float::log_base_10_1_plus_x_prec_round`] for details and special cases.
260 ///
261 /// # Worst-case complexity
262 /// $T(n) = O(n (\log n)^2 \log\log n)$
263 ///
264 /// $M(n) = O(n (\log n)^2)$
265 ///
266 /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
267 ///
268 /// # Panics
269 /// Panics if `prec` is zero.
270 ///
271 /// # Examples
272 /// ```
273 /// use malachite_float::Float;
274 /// use std::cmp::Ordering::*;
275 ///
276 /// let (log, o) = (&Float::from(99)).log_base_10_1_plus_x_prec_ref(10);
277 /// assert_eq!(log.to_string(), "2.0"); // log_10(100) = 2
278 /// assert_eq!(o, Equal);
279 ///
280 /// let (log, o) = (&Float::from(7)).log_base_10_1_plus_x_prec_ref(30);
281 /// assert_eq!(log.to_string(), "0.903089987"); // log_10(8)
282 /// assert_eq!(o, Greater);
283 /// ```
284 #[inline]
285 pub fn log_base_10_1_plus_x_prec_ref(&self, prec: u64) -> (Self, Ordering) {
286 self.log_base_10_1_plus_x_prec_round_ref(prec, Nearest)
287 }
288
289 /// Computes $\log_{10}(1+x)$, where $x$ is a [`Float`], rounding the result to the precision of
290 /// the input and with the specified rounding mode. The [`Float`] is taken by value. An
291 /// [`Ordering`] is also returned, indicating whether the rounded value is less than, equal to,
292 /// or greater than the exact value.
293 ///
294 /// See [`Float::log_base_10_1_plus_x_prec_round`] for details and special cases.
295 ///
296 /// # Worst-case complexity
297 /// $T(n) = O(n (\log n)^2 \log\log n)$
298 ///
299 /// $M(n) = O(n (\log n)^2)$
300 ///
301 /// where $T$ is time, $M$ is additional memory, and $n$ is the precision of the input.
302 ///
303 /// # Panics
304 /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input's
305 /// precision.
306 ///
307 /// # Examples
308 /// ```
309 /// use malachite_base::rounding_modes::RoundingMode::*;
310 /// use malachite_float::Float;
311 /// use std::cmp::Ordering::*;
312 ///
313 /// let (log, o) = Float::from(9).log_base_10_1_plus_x_round(Exact);
314 /// assert_eq!(log.to_string(), "1.0"); // log_10(10) = 1
315 /// assert_eq!(o, Equal);
316 ///
317 /// let (log, o) = Float::from(99).log_base_10_1_plus_x_round(Exact);
318 /// assert_eq!(log.to_string(), "2.0"); // log_10(100) = 2
319 /// assert_eq!(o, Equal);
320 /// ```
321 #[inline]
322 pub fn log_base_10_1_plus_x_round(self, rm: RoundingMode) -> (Self, Ordering) {
323 let prec = self.significant_bits();
324 self.log_base_10_1_plus_x_prec_round(prec, rm)
325 }
326
327 /// Computes $\log_{10}(1+x)$, where $x$ is a [`Float`], rounding the result to the precision of
328 /// the input and with the specified rounding mode. The [`Float`] is taken by reference. An
329 /// [`Ordering`] is also returned, indicating whether the rounded value is less than, equal to,
330 /// or greater than the exact value.
331 ///
332 /// See [`Float::log_base_10_1_plus_x_prec_round`] for details and special cases.
333 ///
334 /// # Worst-case complexity
335 /// $T(n) = O(n (\log n)^2 \log\log n)$
336 ///
337 /// $M(n) = O(n (\log n)^2)$
338 ///
339 /// where $T$ is time, $M$ is additional memory, and $n$ is the precision of the input.
340 ///
341 /// # Panics
342 /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input's
343 /// precision.
344 ///
345 /// # Examples
346 /// ```
347 /// use malachite_base::rounding_modes::RoundingMode::*;
348 /// use malachite_float::Float;
349 /// use std::cmp::Ordering::*;
350 ///
351 /// let (log, o) = (&Float::from(99)).log_base_10_1_plus_x_round_ref(Exact);
352 /// assert_eq!(log.to_string(), "2.0"); // log_10(100) = 2
353 /// assert_eq!(o, Equal);
354 ///
355 /// let (log, o) = (&Float::from(9)).log_base_10_1_plus_x_round_ref(Exact);
356 /// assert_eq!(log.to_string(), "1.0"); // log_10(10) = 1
357 /// assert_eq!(o, Equal);
358 /// ```
359 #[inline]
360 pub fn log_base_10_1_plus_x_round_ref(&self, rm: RoundingMode) -> (Self, Ordering) {
361 self.log_base_10_1_plus_x_prec_round_ref(self.significant_bits(), rm)
362 }
363
364 /// Computes $\log_{10}(1+x)$, where $x$ is a [`Float`], in place, rounding the result to the
365 /// specified precision and with the specified rounding mode. An [`Ordering`] is returned,
366 /// indicating whether the rounded value is less than, equal to, or greater than the exact
367 /// value.
368 ///
369 /// See [`Float::log_base_10_1_plus_x_prec_round`] for details and special cases.
370 ///
371 /// # Worst-case complexity
372 /// $T(n) = O(n (\log n)^2 \log\log n)$
373 ///
374 /// $M(n) = O(n (\log n)^2)$
375 ///
376 /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
377 ///
378 /// # Panics
379 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
380 /// with the given precision.
381 ///
382 /// # Examples
383 /// ```
384 /// use malachite_base::rounding_modes::RoundingMode::*;
385 /// use malachite_float::Float;
386 /// use std::cmp::Ordering::*;
387 ///
388 /// let mut x = Float::from(9);
389 /// assert_eq!(x.log_base_10_1_plus_x_prec_round_assign(10, Exact), Equal);
390 /// assert_eq!(x.to_string(), "1.0"); // log_10(10) = 1
391 ///
392 /// let mut x = Float::from(1);
393 /// assert_eq!(x.log_base_10_1_plus_x_prec_round_assign(20, Floor), Less);
394 /// assert_eq!(x.to_string(), "0.3010297"); // log_10(2), rounded down
395 /// ```
396 #[inline]
397 pub fn log_base_10_1_plus_x_prec_round_assign(
398 &mut self,
399 prec: u64,
400 rm: RoundingMode,
401 ) -> Ordering {
402 let (result, o) = core::mem::take(self).log_base_10_1_plus_x_prec_round(prec, rm);
403 *self = result;
404 o
405 }
406
407 /// Computes $\log_{10}(1+x)$, where $x$ is a [`Float`], in place, rounding the result to the
408 /// nearest value of the specified precision. An [`Ordering`] is returned, indicating whether
409 /// the rounded value is less than, equal to, or greater than the exact value.
410 ///
411 /// See [`Float::log_base_10_1_plus_x_prec_round`] for details and special cases.
412 ///
413 /// # Worst-case complexity
414 /// $T(n) = O(n (\log n)^2 \log\log n)$
415 ///
416 /// $M(n) = O(n (\log n)^2)$
417 ///
418 /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
419 ///
420 /// # Panics
421 /// Panics if `prec` is zero.
422 ///
423 /// # Examples
424 /// ```
425 /// use malachite_float::Float;
426 ///
427 /// let mut x = Float::from(9);
428 /// x.log_base_10_1_plus_x_prec_assign(10);
429 /// assert_eq!(x.to_string(), "1.0"); // log_10(10) = 1
430 ///
431 /// let mut x = Float::from(99);
432 /// x.log_base_10_1_plus_x_prec_assign(10);
433 /// assert_eq!(x.to_string(), "2.0"); // log_10(100) = 2
434 /// ```
435 #[inline]
436 pub fn log_base_10_1_plus_x_prec_assign(&mut self, prec: u64) -> Ordering {
437 self.log_base_10_1_plus_x_prec_round_assign(prec, Nearest)
438 }
439
440 /// Computes $\log_{10}(1+x)$, where $x$ is a [`Float`], in place, rounding the result to the
441 /// precision of the input and with the specified rounding mode. An [`Ordering`] is returned,
442 /// indicating whether the rounded value is less than, equal to, or greater than the exact
443 /// value.
444 ///
445 /// See [`Float::log_base_10_1_plus_x_prec_round`] for details and special cases.
446 ///
447 /// # Worst-case complexity
448 /// $T(n) = O(n (\log n)^2 \log\log n)$
449 ///
450 /// $M(n) = O(n (\log n)^2)$
451 ///
452 /// where $T$ is time, $M$ is additional memory, and $n$ is the precision of the input.
453 ///
454 /// # Panics
455 /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input's
456 /// precision.
457 ///
458 /// # Examples
459 /// ```
460 /// use malachite_base::rounding_modes::RoundingMode::*;
461 /// use malachite_float::Float;
462 ///
463 /// let mut x = Float::from(9);
464 /// x.log_base_10_1_plus_x_round_assign(Exact);
465 /// assert_eq!(x.to_string(), "1.0"); // log_10(10) = 1
466 ///
467 /// let mut x = Float::from(99);
468 /// x.log_base_10_1_plus_x_round_assign(Exact);
469 /// assert_eq!(x.to_string(), "2.0"); // log_10(100) = 2
470 /// ```
471 #[inline]
472 pub fn log_base_10_1_plus_x_round_assign(&mut self, rm: RoundingMode) -> Ordering {
473 let prec = self.significant_bits();
474 self.log_base_10_1_plus_x_prec_round_assign(prec, rm)
475 }
476}
477
478impl LogBase10Of1PlusX for Float {
479 type Output = Self;
480
481 /// Computes $\log_{10}(1+x)$, where $x$ is a [`Float`], rounding the result to the nearest
482 /// value of the input's precision. The [`Float`] is taken by value.
483 ///
484 /// $\log_{10}(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, `NaN` is returned. See
485 /// [`Float::log_base_10_1_plus_x_prec_round`] for the other special cases.
486 ///
487 /// # Worst-case complexity
488 /// $T(n) = O(n (\log n)^2 \log\log n)$
489 ///
490 /// $M(n) = O(n (\log n)^2)$
491 ///
492 /// where $T$ is time, $M$ is additional memory, and $n$ is the precision of the input.
493 ///
494 /// # Examples
495 /// ```
496 /// use malachite_base::num::arithmetic::traits::LogBase10Of1PlusX;
497 /// use malachite_float::Float;
498 ///
499 /// assert_eq!(Float::from(9).log_base_10_1_plus_x().to_string(), "1.0"); // log_10(10) = 1
500 /// assert_eq!(Float::from(99).log_base_10_1_plus_x().to_string(), "2.0"); // log_10(100) = 2
501 /// ```
502 #[inline]
503 fn log_base_10_1_plus_x(self) -> Self {
504 let prec = self.significant_bits();
505 self.log_base_10_1_plus_x_prec_round(prec, Nearest).0
506 }
507}
508
509impl LogBase10Of1PlusX for &Float {
510 type Output = Float;
511
512 /// Computes $\log_{10}(1+x)$, where $x$ is a [`Float`], rounding the result to the nearest
513 /// value of the input's precision. The [`Float`] is taken by reference.
514 ///
515 /// $\log_{10}(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, `NaN` is returned. See
516 /// [`Float::log_base_10_1_plus_x_prec_round`] for the other special cases.
517 ///
518 /// # Worst-case complexity
519 /// $T(n) = O(n (\log n)^2 \log\log n)$
520 ///
521 /// $M(n) = O(n (\log n)^2)$
522 ///
523 /// where $T$ is time, $M$ is additional memory, and $n$ is the precision of the input.
524 ///
525 /// # Examples
526 /// ```
527 /// use malachite_base::num::arithmetic::traits::LogBase10Of1PlusX;
528 /// use malachite_float::Float;
529 ///
530 /// assert_eq!((&Float::from(9)).log_base_10_1_plus_x().to_string(), "1.0"); // log_10(10) = 1
531 /// assert_eq!((&Float::from(99)).log_base_10_1_plus_x().to_string(), "2.0"); // log_10(100) = 2
532 /// ```
533 #[inline]
534 fn log_base_10_1_plus_x(self) -> Float {
535 self.log_base_10_1_plus_x_prec_round_ref(self.significant_bits(), Nearest)
536 .0
537 }
538}
539
540impl LogBase10Of1PlusXAssign for Float {
541 /// Replaces a [`Float`] $x$ with $\log_{10}(1+x)$, rounding the result to the nearest value of
542 /// the input's precision.
543 ///
544 /// $\log_{10}(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, `NaN` is returned. See
545 /// [`Float::log_base_10_1_plus_x_prec_round`] for the other special cases.
546 ///
547 /// # Worst-case complexity
548 /// $T(n) = O(n (\log n)^2 \log\log n)$
549 ///
550 /// $M(n) = O(n (\log n)^2)$
551 ///
552 /// where $T$ is time, $M$ is additional memory, and $n$ is the precision of the input.
553 ///
554 /// # Examples
555 /// ```
556 /// use malachite_base::num::arithmetic::traits::LogBase10Of1PlusXAssign;
557 /// use malachite_float::Float;
558 ///
559 /// let mut x = Float::from(9);
560 /// x.log_base_10_1_plus_x_assign();
561 /// assert_eq!(x.to_string(), "1.0"); // log_10(10) = 1
562 ///
563 /// let mut x = Float::from(99);
564 /// x.log_base_10_1_plus_x_assign();
565 /// assert_eq!(x.to_string(), "2.0"); // log_10(100) = 2
566 /// ```
567 #[inline]
568 fn log_base_10_1_plus_x_assign(&mut self) {
569 let prec = self.significant_bits();
570 self.log_base_10_1_plus_x_prec_round_assign(prec, Nearest);
571 }
572}
573
574/// Computes $\log_{10}(1+x)$, the base-10 logarithm of one plus a primitive float. Using this
575/// function is more accurate than computing `(1 + x).log10()`, both because $1+x$ may not be
576/// representable as a primitive float and because the standard library's `log10` is not always
577/// correctly rounded.
578///
579/// $\log_{10}(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, `NaN` is returned.
580///
581/// $$
582/// f(x) = \log_{10}(1+x)+\varepsilon.
583/// $$
584/// - If $\log_{10}(1+x)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be
585/// 0.
586/// - If $\log_{10}(1+x)$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2
587/// |\log_{10}(1+x)|\rfloor-p}$, where $p$ is precision of the output (typically 24 if `T` is a
588/// [`f32`] and 53 if `T` is a [`f64`], but less if the output is subnormal).
589///
590/// Special cases:
591/// - $f(\text{NaN})=\text{NaN}$
592/// - $f(\infty)=\infty$
593/// - $f(-\infty)=\text{NaN}$
594/// - $f(\pm0.0)=\pm0.0$
595/// - $f(-1.0)=-\infty$
596/// - $f(x)=\text{NaN}$ for $x<-1$
597///
598/// This function can underflow (to a subnormal or zero) when $x$ is close to zero, but it cannot
599/// overflow.
600///
601/// # Worst-case complexity
602/// Constant time and additional memory.
603///
604/// # Examples
605/// ```
606/// use malachite_base::num::basic::traits::NegativeInfinity;
607/// use malachite_base::num::float::NiceFloat;
608/// use malachite_float::arithmetic::log_base_10_1_plus_x::primitive_float_log_base_10_1_plus_x;
609///
610/// assert!(primitive_float_log_base_10_1_plus_x(f32::NAN).is_nan());
611/// assert_eq!(
612/// NiceFloat(primitive_float_log_base_10_1_plus_x(f32::INFINITY)),
613/// NiceFloat(f32::INFINITY)
614/// );
615/// assert_eq!(
616/// NiceFloat(primitive_float_log_base_10_1_plus_x(-1.0f32)),
617/// NiceFloat(f32::NEGATIVE_INFINITY)
618/// );
619/// assert!(primitive_float_log_base_10_1_plus_x(-2.0f32).is_nan());
620/// // log_10(1 + 999) = log_10(1000) = 3
621/// assert_eq!(
622/// NiceFloat(primitive_float_log_base_10_1_plus_x(999.0f32)),
623/// NiceFloat(3.0)
624/// );
625/// // log_10(1 + 9) = log_10(10) = 1
626/// assert_eq!(
627/// NiceFloat(primitive_float_log_base_10_1_plus_x(9.0f32)),
628/// NiceFloat(1.0)
629/// );
630/// // log_10(1 + 1) = log_10(2)
631/// assert_eq!(
632/// NiceFloat(primitive_float_log_base_10_1_plus_x(1.0f32)),
633/// NiceFloat(std::f32::consts::LOG10_2)
634/// );
635/// ```
636#[inline]
637#[allow(clippy::type_repetition_in_bounds)]
638pub fn primitive_float_log_base_10_1_plus_x<T: PrimitiveFloat>(x: T) -> T
639where
640 Float: From<T> + PartialOrd<T>,
641 for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
642{
643 emulate_float_to_float_fn(Float::log_base_10_1_plus_x_prec, x)
644}