malachite_float/float/arithmetic/log_base_2_1_plus_x.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 AriC 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::{Infinity, NaN, Zero};
16use crate::{Float, emulate_float_to_float_fn, float_infinity, float_nan, float_negative_infinity};
17use core::cmp::Ordering::{self, *};
18use core::cmp::max;
19use malachite_base::num::arithmetic::traits::{
20 CeilingLogBase2, IsPowerOf2, LogBase2Of1PlusX, LogBase2Of1PlusXAssign,
21};
22use malachite_base::num::basic::floats::PrimitiveFloat;
23use malachite_base::num::basic::integers::PrimitiveInt;
24use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom};
25use malachite_base::num::logic::traits::SignificantBits;
26use malachite_base::rounding_modes::RoundingMode::{self, *};
27use malachite_nz::natural::arithmetic::float::round::{
28 float_can_round, float_significand_leading_ones,
29};
30use malachite_nz::platform::Limb;
31
32// Returns `Some(k)` if `1 + x` is exactly $2^k$ (equivalently $x = 2^k - 1$), and `None` otherwise.
33// The input must be finite, nonzero, and greater than $-1$.
34//
35// `1 + x` is a power of 2 exactly when the mantissa of `x` is a run of ones (the value $2^j - 1$),
36// the exponent of `x` equals $j$ (so `x` is the integer $2^j - 1$ and $k = j$) when `x` is
37// positive, or the exponent of `x` is 0 (so `x` is $-(1 - 2^{-j})$ and $k = -j$) when `x` is
38// negative. This replaces MPFR's `mpfr_log2p1_isexact`, which adds 1 to `x` and tests for a power
39// of 2; we test the significand's bits directly.
40pub(crate) fn log_base_2_1_plus_x_exact(x: &Float) -> Option<i64> {
41 let j = i64::exact_from(float_significand_leading_ones(
42 x.significand_ref().unwrap(),
43 )?);
44 let e = i64::from(x.get_exponent().unwrap());
45 if *x > 0u32 {
46 (e == j).then_some(j)
47 } else {
48 (e == 0).then_some(-j)
49 }
50}
51
52// If `x` is $2^k$ for a `k` large enough that the Ziv loop would never converge, returns the
53// correctly-rounded value of $\log_2(1+x)$; otherwise returns `None`. The input must be finite,
54// nonzero, and greater than $-1$, and `1 + x` must not be a power of 2.
55//
56// This is mpfr_log2p1_special from log2p1.c, MPFR 4.3.0. For $x = 2^k$ with $k \geq 1$ we have $k <
57// \log_2(1+x) < k + 2/x$. When $2/x$ is below a quarter of an ulp of $k$, the result rounds the
58// same way as $k$ stepped up by a single ulp, so the rounding can be decided directly.
59fn log_base_2_1_plus_x_special(
60 x: &Float,
61 prec: u64,
62 rm: RoundingMode,
63) -> Option<(Float, Ordering)> {
64 if !x.is_power_of_2() {
65 return None;
66 }
67 let expx = i64::from(x.get_exponent().unwrap());
68 // x = 2^k
69 let k = expx - 1;
70 if k <= 0 {
71 return None;
72 }
73 // expk is the exponent of k. We have 2 / x < 2^(2 - expx), so if 2 - expx < expk - prec - 1,
74 // then 2 / x < (1/4) ulp(k) and the correct rounding can be decided.
75 let expk = i64::exact_from(u64::exact_from(k).ceiling_log_base_2());
76 if 2 - expx >= expk - i64::exact_from(prec) - 1 {
77 return None;
78 }
79 // log_2(1 + x) lies in (k, k + 1/4 ulp(k)); round k stepped up by one ulp.
80 let high_prec = max(prec + 2, Limb::WIDTH);
81 let mut t = Float::from_signed_prec(k, high_prec).0;
82 t.increment();
83 Some(Float::from_float_prec_round(t, prec, rm))
84}
85
86// The computation of log2p1 is done by log_base_2_1_plus_x(x) = ln_1_plus_x(x) / ln(2).
87//
88// This is mpfr_log2p1 from log2p1.c, MPFR 4.3.0, where the input is finite and nonzero.
89fn log_base_2_1_plus_x_prec_round_normal(
90 x: &Float,
91 prec: u64,
92 rm: RoundingMode,
93) -> (Float, Ordering) {
94 // log_2(1 + x) is undefined for x < -1.
95 match x.partial_cmp(&-1i32).unwrap() {
96 Equal => return (float_negative_infinity!(), Equal),
97 Less => return (float_nan!(), Equal),
98 _ => {}
99 }
100 // If 1 + x is exactly a power of 2, the result is an integer (subject to rounding at the target
101 // precision).
102 if let Some(k) = log_base_2_1_plus_x_exact(x) {
103 return Float::from_signed_prec_round(k, prec, rm);
104 }
105 // The result is never exactly representable otherwise.
106 assert_ne!(rm, Exact, "Inexact log_base_2_1_plus_x");
107 // If x = 2^k with k huge, the Ziv loop would never converge; handle it specially.
108 if let Some(result) = log_base_2_1_plus_x_special(x, prec, rm) {
109 return result;
110 }
111 // General case. Compute the precision of the intermediary variable: the optimal number of bits,
112 // see algorithms.tex.
113 let mut working_prec = prec + prec.ceiling_log_base_2() + 6;
114 let mut increment = Limb::WIDTH;
115 loop {
116 // ln(1 + x) / ln(2). This is log_2(1 + x) * (1 + theta)^3 with |theta| < 2^-working_prec,
117 // and |(1 + theta)^3 - 1| < 4 * theta for working_prec >= 2, i.e. 4 ulps of error.
118 let t = x
119 .ln_1_plus_x_prec_ref(working_prec)
120 .0
121 .div_prec(Float::ln_2_prec(working_prec).0, working_prec)
122 .0;
123 if float_can_round(t.significand_ref().unwrap(), working_prec - 2, prec, rm) {
124 return Float::from_float_prec_round(t, prec, rm);
125 }
126 // Increase the precision.
127 working_prec += increment;
128 increment = working_prec >> 1;
129 }
130}
131
132impl Float {
133 /// Computes $\log_2(1+x)$, where $x$ is a [`Float`], rounding the result to the specified
134 /// precision and with the specified rounding mode. The [`Float`] is taken by value. An
135 /// [`Ordering`] is also returned, indicating whether the rounded value is less than, equal to,
136 /// or greater than the exact value. Although `NaN`s are not comparable to any [`Float`],
137 /// whenever this function returns a `NaN` it also returns `Equal`.
138 ///
139 /// $\log_2(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, `NaN` is returned.
140 ///
141 /// See [`RoundingMode`] for a description of the possible rounding modes.
142 ///
143 /// $$
144 /// f(x,p,m) = \log_2(1+x)+\varepsilon.
145 /// $$
146 /// - If $\log_2(1+x)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to
147 /// be 0.
148 /// - If $\log_2(1+x)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
149 /// 2^{\lfloor\log_2 |\log_2(1+x)|\rfloor-p+1}$.
150 /// - If $\log_2(1+x)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
151 /// 2^{\lfloor\log_2 |\log_2(1+x)|\rfloor-p}$.
152 ///
153 /// If the output has a precision, it is `prec`.
154 ///
155 /// Special cases:
156 /// - $f(\text{NaN},p,m)=\text{NaN}$
157 /// - $f(\infty,p,m)=\infty$
158 /// - $f(-\infty,p,m)=\text{NaN}$
159 /// - $f(\pm0.0,p,m)=\pm0.0$
160 /// - $f(-1,p,m)=-\infty$
161 /// - $f(x,p,m)=\text{NaN}$ for $x<-1$
162 /// - $f(x,p,m)=k$ when $1+x=2^k$. The result is the integer $k$ (subject to rounding at
163 /// precision $p$, and exact iff $k$ is representable with precision $p$). This covers $x$ a
164 /// power of 2 minus 1 (e.g. $x=1\to1$, $x=3\to2$) and negative $x$ such as $x=-1/2\to-1$ and
165 /// $x=-3/4\to-2$.
166 ///
167 /// Neither overflow nor underflow is possible.
168 ///
169 /// If you know you'll be using `Nearest`, consider using [`Float::log_base_2_1_plus_x_prec`]
170 /// instead. If you know that your target precision is the precision of the input, consider
171 /// using [`Float::log_base_2_1_plus_x_round`] instead. If both of these things are true,
172 /// consider using [`Float::log_base_2_1_plus_x`] instead.
173 ///
174 /// # Worst-case complexity
175 /// $T(n, m) = O(n (\log n)^2 \log\log n + m)$
176 ///
177 /// $M(n, m) = O(n \log n + m)$
178 ///
179 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
180 /// `self.significant_bits()`.
181 ///
182 /// # Panics
183 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
184 /// with the given precision. (The result is exactly representable only when the input is `NaN`,
185 /// infinite, zero, $-1$, less than $-1$, or a value for which $1+x$ is a power of 2 whose
186 /// base-2 logarithm is representable with the given precision.)
187 ///
188 /// # Examples
189 /// ```
190 /// use malachite_base::rounding_modes::RoundingMode::*;
191 /// use malachite_float::Float;
192 /// use std::cmp::Ordering::*;
193 ///
194 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
195 /// .0
196 /// .log_base_2_1_plus_x_prec_round(5, Floor);
197 /// assert_eq!(log.to_string(), "3.38");
198 /// assert_eq!(o, Less);
199 ///
200 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
201 /// .0
202 /// .log_base_2_1_plus_x_prec_round(5, Ceiling);
203 /// assert_eq!(log.to_string(), "3.50");
204 /// assert_eq!(o, Greater);
205 ///
206 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
207 /// .0
208 /// .log_base_2_1_plus_x_prec_round(5, Nearest);
209 /// assert_eq!(log.to_string(), "3.50");
210 /// assert_eq!(o, Greater);
211 ///
212 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
213 /// .0
214 /// .log_base_2_1_plus_x_prec_round(20, Floor);
215 /// assert_eq!(log.to_string(), "3.4594307");
216 /// assert_eq!(o, Less);
217 ///
218 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
219 /// .0
220 /// .log_base_2_1_plus_x_prec_round(20, Ceiling);
221 /// assert_eq!(log.to_string(), "3.4594345");
222 /// assert_eq!(o, Greater);
223 ///
224 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
225 /// .0
226 /// .log_base_2_1_plus_x_prec_round(20, Nearest);
227 /// assert_eq!(log.to_string(), "3.4594307");
228 /// assert_eq!(o, Less);
229 /// ```
230 #[inline]
231 pub fn log_base_2_1_plus_x_prec_round(self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
232 assert_ne!(prec, 0);
233 match self {
234 Self(NaN | Infinity { sign: false }) => (float_nan!(), Equal),
235 float_infinity!() => (float_infinity!(), Equal),
236 // log_base_2_1_plus_x(±0) = ±0
237 Self(Zero { .. }) => (self, Equal),
238 _ => log_base_2_1_plus_x_prec_round_normal(&self, prec, rm),
239 }
240 }
241
242 /// Computes $\log_2(1+x)$, where $x$ is a [`Float`], rounding the result to the specified
243 /// precision and with the specified rounding mode. The [`Float`] is taken by reference. An
244 /// [`Ordering`] is also returned, indicating whether the rounded value is less than, equal to,
245 /// or greater than the exact value. Although `NaN`s are not comparable to any [`Float`],
246 /// whenever this function returns a `NaN` it also returns `Equal`.
247 ///
248 /// $\log_2(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, `NaN` is returned.
249 ///
250 /// See [`RoundingMode`] for a description of the possible rounding modes.
251 ///
252 /// $$
253 /// f(x,p,m) = \log_2(1+x)+\varepsilon.
254 /// $$
255 /// - If $\log_2(1+x)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to
256 /// be 0.
257 /// - If $\log_2(1+x)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
258 /// 2^{\lfloor\log_2 |\log_2(1+x)|\rfloor-p+1}$.
259 /// - If $\log_2(1+x)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
260 /// 2^{\lfloor\log_2 |\log_2(1+x)|\rfloor-p}$.
261 ///
262 /// If the output has a precision, it is `prec`.
263 ///
264 /// Special cases:
265 /// - $f(\text{NaN},p,m)=\text{NaN}$
266 /// - $f(\infty,p,m)=\infty$
267 /// - $f(-\infty,p,m)=\text{NaN}$
268 /// - $f(\pm0.0,p,m)=\pm0.0$
269 /// - $f(-1,p,m)=-\infty$
270 /// - $f(x,p,m)=\text{NaN}$ for $x<-1$
271 /// - $f(x,p,m)=k$ when $1+x=2^k$. The result is the integer $k$ (subject to rounding at
272 /// precision $p$, and exact iff $k$ is representable with precision $p$). This covers $x$ a
273 /// power of 2 minus 1 (e.g. $x=1\to1$, $x=3\to2$) and negative $x$ such as $x=-1/2\to-1$ and
274 /// $x=-3/4\to-2$.
275 ///
276 /// Neither overflow nor underflow is possible.
277 ///
278 /// If you know you'll be using `Nearest`, consider using
279 /// [`Float::log_base_2_1_plus_x_prec_ref`] instead. If you know that your target precision is
280 /// the precision of the input, consider using [`Float::log_base_2_1_plus_x_round_ref`] instead.
281 /// If both of these things are true, consider using `(&Float).log_base_2_1_plus_x()` instead.
282 ///
283 /// # Worst-case complexity
284 /// $T(n, m) = O(n (\log n)^2 \log\log n + m)$
285 ///
286 /// $M(n, m) = O(n \log n + m)$
287 ///
288 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
289 /// `self.significant_bits()`.
290 ///
291 /// # Panics
292 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
293 /// with the given precision. (The result is exactly representable only when the input is `NaN`,
294 /// infinite, zero, $-1$, less than $-1$, or a value for which $1+x$ is a power of 2 whose
295 /// base-2 logarithm is representable with the given precision.)
296 ///
297 /// # Examples
298 /// ```
299 /// use malachite_base::rounding_modes::RoundingMode::*;
300 /// use malachite_float::Float;
301 /// use std::cmp::Ordering::*;
302 ///
303 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
304 /// .0
305 /// .log_base_2_1_plus_x_prec_round_ref(5, Floor);
306 /// assert_eq!(log.to_string(), "3.38");
307 /// assert_eq!(o, Less);
308 ///
309 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
310 /// .0
311 /// .log_base_2_1_plus_x_prec_round_ref(5, Ceiling);
312 /// assert_eq!(log.to_string(), "3.50");
313 /// assert_eq!(o, Greater);
314 ///
315 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
316 /// .0
317 /// .log_base_2_1_plus_x_prec_round_ref(5, Nearest);
318 /// assert_eq!(log.to_string(), "3.50");
319 /// assert_eq!(o, Greater);
320 ///
321 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
322 /// .0
323 /// .log_base_2_1_plus_x_prec_round_ref(20, Floor);
324 /// assert_eq!(log.to_string(), "3.4594307");
325 /// assert_eq!(o, Less);
326 ///
327 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
328 /// .0
329 /// .log_base_2_1_plus_x_prec_round_ref(20, Ceiling);
330 /// assert_eq!(log.to_string(), "3.4594345");
331 /// assert_eq!(o, Greater);
332 ///
333 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
334 /// .0
335 /// .log_base_2_1_plus_x_prec_round_ref(20, Nearest);
336 /// assert_eq!(log.to_string(), "3.4594307");
337 /// assert_eq!(o, Less);
338 /// ```
339 #[inline]
340 pub fn log_base_2_1_plus_x_prec_round_ref(
341 &self,
342 prec: u64,
343 rm: RoundingMode,
344 ) -> (Self, Ordering) {
345 assert_ne!(prec, 0);
346 match self {
347 Self(NaN | Infinity { sign: false }) => (float_nan!(), Equal),
348 float_infinity!() => (float_infinity!(), Equal),
349 // log_base_2_1_plus_x(±0) = ±0
350 Self(Zero { .. }) => (self.clone(), Equal),
351 _ => log_base_2_1_plus_x_prec_round_normal(self, prec, rm),
352 }
353 }
354
355 /// Computes $\log_2(1+x)$, where $x$ is a [`Float`], rounding the result to the nearest value
356 /// of the specified precision. The [`Float`] is taken by value. An [`Ordering`] is also
357 /// returned, indicating whether the rounded value is less than, equal to, or greater than the
358 /// exact value. Although `NaN`s are not comparable to any [`Float`], whenever this function
359 /// returns a `NaN` it also returns `Equal`.
360 ///
361 /// $\log_2(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, `NaN` is returned.
362 ///
363 /// If the result is equidistant from two [`Float`]s with the specified precision, the [`Float`]
364 /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of
365 /// the `Nearest` rounding mode.
366 ///
367 /// $$
368 /// f(x,p) = \log_2(1+x)+\varepsilon.
369 /// $$
370 /// - If $\log_2(1+x)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to
371 /// be 0.
372 /// - If $\log_2(1+x)$ is finite and nonzero, then $|\varepsilon| \leq 2^{\lfloor\log_2
373 /// |\log_2(1+x)|\rfloor-p}$.
374 ///
375 /// If the output has a precision, it is `prec`.
376 ///
377 /// Special cases:
378 /// - $f(\text{NaN},p)=\text{NaN}$
379 /// - $f(\infty,p)=\infty$
380 /// - $f(-\infty,p)=\text{NaN}$
381 /// - $f(\pm0.0,p)=\pm0.0$
382 /// - $f(-1,p)=-\infty$
383 /// - $f(x,p)=\text{NaN}$ for $x<-1$
384 /// - $f(x,p)=k$ when $1+x=2^k$. The result is the integer $k$ (subject to rounding at precision
385 /// $p$, and exact iff $k$ is representable with precision $p$). This covers $x$ a power of 2
386 /// minus 1 (e.g. $x=1\to1$, $x=3\to2$) and negative $x$ such as $x=-1/2\to-1$ and
387 /// $x=-3/4\to-2$.
388 ///
389 /// Neither overflow nor underflow is possible.
390 ///
391 /// If you want to use a rounding mode other than `Nearest`, consider using
392 /// [`Float::log_base_2_1_plus_x_prec_round`] instead. If you know that your target precision is
393 /// the precision of the input, consider using [`Float::log_base_2_1_plus_x`] instead.
394 ///
395 /// # Worst-case complexity
396 /// $T(n, m) = O(n (\log n)^2 \log\log n + m)$
397 ///
398 /// $M(n, m) = O(n \log n + m)$
399 ///
400 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
401 /// `self.significant_bits()`.
402 ///
403 /// # Panics
404 /// Panics if `prec` is zero.
405 ///
406 /// # Examples
407 /// ```
408 /// use malachite_base::num::basic::traits::One;
409 /// use malachite_float::Float;
410 /// use std::cmp::Ordering::*;
411 ///
412 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
413 /// .0
414 /// .log_base_2_1_plus_x_prec(5);
415 /// assert_eq!(log.to_string(), "3.50");
416 /// assert_eq!(o, Greater);
417 ///
418 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
419 /// .0
420 /// .log_base_2_1_plus_x_prec(20);
421 /// assert_eq!(log.to_string(), "3.4594307");
422 /// assert_eq!(o, Less);
423 ///
424 /// let (log, o) = Float::ONE.log_base_2_1_plus_x_prec(20);
425 /// assert_eq!(log.to_string(), "1.0000000");
426 /// assert_eq!(o, Equal);
427 /// ```
428 #[inline]
429 pub fn log_base_2_1_plus_x_prec(self, prec: u64) -> (Self, Ordering) {
430 self.log_base_2_1_plus_x_prec_round(prec, Nearest)
431 }
432
433 /// Computes $\log_2(1+x)$, where $x$ is a [`Float`], rounding the result to the nearest value
434 /// of the specified precision. The [`Float`] is taken by reference. An [`Ordering`] is also
435 /// returned, indicating whether the rounded value is less than, equal to, or greater than the
436 /// exact value. Although `NaN`s are not comparable to any [`Float`], whenever this function
437 /// returns a `NaN` it also returns `Equal`.
438 ///
439 /// $\log_2(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, `NaN` is returned.
440 ///
441 /// If the result is equidistant from two [`Float`]s with the specified precision, the [`Float`]
442 /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of
443 /// the `Nearest` rounding mode.
444 ///
445 /// $$
446 /// f(x,p) = \log_2(1+x)+\varepsilon.
447 /// $$
448 /// - If $\log_2(1+x)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to
449 /// be 0.
450 /// - If $\log_2(1+x)$ is finite and nonzero, then $|\varepsilon| \leq 2^{\lfloor\log_2
451 /// |\log_2(1+x)|\rfloor-p}$.
452 ///
453 /// If the output has a precision, it is `prec`.
454 ///
455 /// Special cases:
456 /// - $f(\text{NaN},p)=\text{NaN}$
457 /// - $f(\infty,p)=\infty$
458 /// - $f(-\infty,p)=\text{NaN}$
459 /// - $f(\pm0.0,p)=\pm0.0$
460 /// - $f(-1,p)=-\infty$
461 /// - $f(x,p)=\text{NaN}$ for $x<-1$
462 /// - $f(x,p)=k$ when $1+x=2^k$. The result is the integer $k$ (subject to rounding at precision
463 /// $p$, and exact iff $k$ is representable with precision $p$). This covers $x$ a power of 2
464 /// minus 1 (e.g. $x=1\to1$, $x=3\to2$) and negative $x$ such as $x=-1/2\to-1$ and
465 /// $x=-3/4\to-2$.
466 ///
467 /// Neither overflow nor underflow is possible.
468 ///
469 /// If you want to use a rounding mode other than `Nearest`, consider using
470 /// [`Float::log_base_2_1_plus_x_prec_round_ref`] instead. If you know that your target
471 /// precision is the precision of the input, consider using `(&Float).log_base_2_1_plus_x()`
472 /// instead.
473 ///
474 /// # Worst-case complexity
475 /// $T(n, m) = O(n (\log n)^2 \log\log n + m)$
476 ///
477 /// $M(n, m) = O(n \log n + m)$
478 ///
479 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
480 /// `self.significant_bits()`.
481 ///
482 /// # Panics
483 /// Panics if `prec` is zero.
484 ///
485 /// # Examples
486 /// ```
487 /// use malachite_base::num::basic::traits::One;
488 /// use malachite_float::Float;
489 /// use std::cmp::Ordering::*;
490 ///
491 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
492 /// .0
493 /// .log_base_2_1_plus_x_prec_ref(5);
494 /// assert_eq!(log.to_string(), "3.50");
495 /// assert_eq!(o, Greater);
496 ///
497 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
498 /// .0
499 /// .log_base_2_1_plus_x_prec_ref(20);
500 /// assert_eq!(log.to_string(), "3.4594307");
501 /// assert_eq!(o, Less);
502 ///
503 /// let (log, o) = Float::ONE.log_base_2_1_plus_x_prec_ref(20);
504 /// assert_eq!(log.to_string(), "1.0000000");
505 /// assert_eq!(o, Equal);
506 /// ```
507 #[inline]
508 pub fn log_base_2_1_plus_x_prec_ref(&self, prec: u64) -> (Self, Ordering) {
509 self.log_base_2_1_plus_x_prec_round_ref(prec, Nearest)
510 }
511
512 /// Computes $\log_2(1+x)$, where $x$ is a [`Float`], rounding the result with the specified
513 /// rounding mode. The [`Float`] is taken by value. An [`Ordering`] is also returned, indicating
514 /// whether the rounded value is less than, equal to, or greater than the exact value. Although
515 /// `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN` it also
516 /// returns `Equal`.
517 ///
518 /// $\log_2(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, `NaN` is returned.
519 ///
520 /// The precision of the output is the precision of the input. See [`RoundingMode`] for a
521 /// description of the possible rounding modes.
522 ///
523 /// $$
524 /// f(x,m) = \log_2(1+x)+\varepsilon.
525 /// $$
526 /// - If $\log_2(1+x)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to
527 /// be 0.
528 /// - If $\log_2(1+x)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
529 /// 2^{\lfloor\log_2 |\log_2(1+x)|\rfloor-p+1}$, where $p$ is the precision of the input.
530 /// - If $\log_2(1+x)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
531 /// 2^{\lfloor\log_2 |\log_2(1+x)|\rfloor-p}$, where $p$ is the precision of the input.
532 ///
533 /// If the output has a precision, it is the precision of the input.
534 ///
535 /// Special cases:
536 /// - $f(\text{NaN},m)=\text{NaN}$
537 /// - $f(\infty,m)=\infty$
538 /// - $f(-\infty,m)=\text{NaN}$
539 /// - $f(\pm0.0,m)=\pm0.0$
540 /// - $f(-1,m)=-\infty$
541 /// - $f(x,m)=\text{NaN}$ for $x<-1$
542 /// - $f(x,m)=k$ when $1+x=2^k$. The result is the integer $k$ (subject to rounding at the input
543 /// precision $p$, and exact iff $k$ is representable with precision $p$). This covers $x$ a
544 /// power of 2 minus 1 (e.g. $x=1\to1$, $x=3\to2$) and negative $x$ such as $x=-1/2\to-1$ and
545 /// $x=-3/4\to-2$.
546 ///
547 /// Neither overflow nor underflow is possible.
548 ///
549 /// If you want to specify an output precision, consider using
550 /// [`Float::log_base_2_1_plus_x_prec_round`] instead. If you know you'll be using the `Nearest`
551 /// rounding mode, consider using [`Float::log_base_2_1_plus_x`] instead.
552 ///
553 /// # Worst-case complexity
554 /// $T(n) = O(n (\log n)^2 \log\log n)$
555 ///
556 /// $M(n) = O(n \log n)$
557 ///
558 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`.
559 ///
560 /// # Panics
561 /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input
562 /// precision. (The result is exactly representable only when the input is `NaN`, infinite,
563 /// zero, $-1$, less than $-1$, or a value for which $1+x$ is a power of 2 whose base-2
564 /// logarithm is representable with the given precision.)
565 ///
566 /// # Examples
567 /// ```
568 /// use malachite_base::rounding_modes::RoundingMode::*;
569 /// use malachite_float::Float;
570 /// use std::cmp::Ordering::*;
571 ///
572 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
573 /// .0
574 /// .log_base_2_1_plus_x_round(Floor);
575 /// assert_eq!(log.to_string(), "3.4594316186372972561993630467247");
576 /// assert_eq!(o, Less);
577 ///
578 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
579 /// .0
580 /// .log_base_2_1_plus_x_round(Ceiling);
581 /// assert_eq!(log.to_string(), "3.4594316186372972561993630467279");
582 /// assert_eq!(o, Greater);
583 ///
584 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
585 /// .0
586 /// .log_base_2_1_plus_x_round(Nearest);
587 /// assert_eq!(log.to_string(), "3.4594316186372972561993630467247");
588 /// assert_eq!(o, Less);
589 /// ```
590 #[inline]
591 pub fn log_base_2_1_plus_x_round(self, rm: RoundingMode) -> (Self, Ordering) {
592 let prec = self.significant_bits();
593 self.log_base_2_1_plus_x_prec_round(prec, rm)
594 }
595
596 /// Computes $\log_2(1+x)$, where $x$ is a [`Float`], rounding the result with the specified
597 /// rounding mode. The [`Float`] is taken by reference. An [`Ordering`] is also returned,
598 /// indicating whether the rounded value is less than, equal to, or greater than the exact
599 /// value. Although `NaN`s are not comparable to any [`Float`], whenever this function returns a
600 /// `NaN` it also returns `Equal`.
601 ///
602 /// $\log_2(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, `NaN` is returned.
603 ///
604 /// The precision of the output is the precision of the input. See [`RoundingMode`] for a
605 /// description of the possible rounding modes.
606 ///
607 /// $$
608 /// f(x,m) = \log_2(1+x)+\varepsilon.
609 /// $$
610 /// - If $\log_2(1+x)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to
611 /// be 0.
612 /// - If $\log_2(1+x)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
613 /// 2^{\lfloor\log_2 |\log_2(1+x)|\rfloor-p+1}$, where $p$ is the precision of the input.
614 /// - If $\log_2(1+x)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
615 /// 2^{\lfloor\log_2 |\log_2(1+x)|\rfloor-p}$, where $p$ is the precision of the input.
616 ///
617 /// If the output has a precision, it is the precision of the input.
618 ///
619 /// Special cases:
620 /// - $f(\text{NaN},m)=\text{NaN}$
621 /// - $f(\infty,m)=\infty$
622 /// - $f(-\infty,m)=\text{NaN}$
623 /// - $f(\pm0.0,m)=\pm0.0$
624 /// - $f(-1,m)=-\infty$
625 /// - $f(x,m)=\text{NaN}$ for $x<-1$
626 /// - $f(x,m)=k$ when $1+x=2^k$. The result is the integer $k$ (subject to rounding at the input
627 /// precision $p$, and exact iff $k$ is representable with precision $p$). This covers $x$ a
628 /// power of 2 minus 1 (e.g. $x=1\to1$, $x=3\to2$) and negative $x$ such as $x=-1/2\to-1$ and
629 /// $x=-3/4\to-2$.
630 ///
631 /// Neither overflow nor underflow is possible.
632 ///
633 /// If you want to specify an output precision, consider using
634 /// [`Float::log_base_2_1_plus_x_prec_round_ref`] instead. If you know you'll be using the
635 /// `Nearest` rounding mode, consider using `(&Float).log_base_2_1_plus_x()` instead.
636 ///
637 /// # Worst-case complexity
638 /// $T(n) = O(n (\log n)^2 \log\log n)$
639 ///
640 /// $M(n) = O(n \log n)$
641 ///
642 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`.
643 ///
644 /// # Panics
645 /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input
646 /// precision. (The result is exactly representable only when the input is `NaN`, infinite,
647 /// zero, $-1$, less than $-1$, or a value for which $1+x$ is a power of 2 whose base-2
648 /// logarithm is representable with the given precision.)
649 ///
650 /// # Examples
651 /// ```
652 /// use malachite_base::rounding_modes::RoundingMode::*;
653 /// use malachite_float::Float;
654 /// use std::cmp::Ordering::*;
655 ///
656 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
657 /// .0
658 /// .log_base_2_1_plus_x_round_ref(Floor);
659 /// assert_eq!(log.to_string(), "3.4594316186372972561993630467247");
660 /// assert_eq!(o, Less);
661 ///
662 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
663 /// .0
664 /// .log_base_2_1_plus_x_round_ref(Ceiling);
665 /// assert_eq!(log.to_string(), "3.4594316186372972561993630467279");
666 /// assert_eq!(o, Greater);
667 ///
668 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
669 /// .0
670 /// .log_base_2_1_plus_x_round_ref(Nearest);
671 /// assert_eq!(log.to_string(), "3.4594316186372972561993630467247");
672 /// assert_eq!(o, Less);
673 /// ```
674 #[inline]
675 pub fn log_base_2_1_plus_x_round_ref(&self, rm: RoundingMode) -> (Self, Ordering) {
676 let prec = self.significant_bits();
677 self.log_base_2_1_plus_x_prec_round_ref(prec, rm)
678 }
679
680 /// Computes $\log_2(1+x)$, where $x$ is a [`Float`], in place, rounding the result to the
681 /// specified precision and with the specified rounding mode. An [`Ordering`] is returned,
682 /// indicating whether the rounded value is less than, equal to, or greater than the exact
683 /// value. Although `NaN`s are not comparable to any [`Float`], whenever this function sets the
684 /// [`Float`] to `NaN` it also returns `Equal`.
685 ///
686 /// $\log_2(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, the [`Float`] is set to `NaN`.
687 ///
688 /// See [`RoundingMode`] for a description of the possible rounding modes.
689 ///
690 /// $$
691 /// x \gets \log_2(1+x)+\varepsilon.
692 /// $$
693 /// - If $\log_2(1+x)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to
694 /// be 0.
695 /// - If $\log_2(1+x)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
696 /// 2^{\lfloor\log_2 |\log_2(1+x)|\rfloor-p+1}$.
697 /// - If $\log_2(1+x)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
698 /// 2^{\lfloor\log_2 |\log_2(1+x)|\rfloor-p}$.
699 ///
700 /// If the output has a precision, it is `prec`.
701 ///
702 /// See the [`Float::log_base_2_1_plus_x_prec_round`] documentation for information on special
703 /// cases, overflow, and underflow.
704 ///
705 /// If you know you'll be using `Nearest`, consider using
706 /// [`Float::log_base_2_1_plus_x_prec_assign`] instead. If you know that your target precision
707 /// is the precision of the input, consider using [`Float::log_base_2_1_plus_x_round_assign`]
708 /// instead. If both of these things are true, consider using
709 /// [`Float::log_base_2_1_plus_x_assign`] instead.
710 ///
711 /// # Worst-case complexity
712 /// $T(n, m) = O(n (\log n)^2 \log\log n + m)$
713 ///
714 /// $M(n, m) = O(n \log n + m)$
715 ///
716 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
717 /// `self.significant_bits()`.
718 ///
719 /// # Panics
720 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
721 /// with the given precision. (The result is exactly representable only when the input is `NaN`,
722 /// infinite, zero, $-1$, less than $-1$, or a value for which $1+x$ is a power of 2 whose
723 /// base-2 logarithm is representable with the given precision.)
724 ///
725 /// # Examples
726 /// ```
727 /// use malachite_base::rounding_modes::RoundingMode::*;
728 /// use malachite_float::Float;
729 /// use std::cmp::Ordering::*;
730 ///
731 /// let mut x = Float::from_unsigned_prec(10u32, 100).0;
732 /// assert_eq!(x.log_base_2_1_plus_x_prec_round_assign(5, Floor), Less);
733 /// assert_eq!(x.to_string(), "3.38");
734 ///
735 /// let mut x = Float::from_unsigned_prec(10u32, 100).0;
736 /// assert_eq!(x.log_base_2_1_plus_x_prec_round_assign(5, Ceiling), Greater);
737 /// assert_eq!(x.to_string(), "3.50");
738 ///
739 /// let mut x = Float::from_unsigned_prec(10u32, 100).0;
740 /// assert_eq!(x.log_base_2_1_plus_x_prec_round_assign(5, Nearest), Greater);
741 /// assert_eq!(x.to_string(), "3.50");
742 ///
743 /// let mut x = Float::from_unsigned_prec(10u32, 100).0;
744 /// assert_eq!(x.log_base_2_1_plus_x_prec_round_assign(20, Floor), Less);
745 /// assert_eq!(x.to_string(), "3.4594307");
746 ///
747 /// let mut x = Float::from_unsigned_prec(10u32, 100).0;
748 /// assert_eq!(
749 /// x.log_base_2_1_plus_x_prec_round_assign(20, Ceiling),
750 /// Greater
751 /// );
752 /// assert_eq!(x.to_string(), "3.4594345");
753 ///
754 /// let mut x = Float::from_unsigned_prec(10u32, 100).0;
755 /// assert_eq!(x.log_base_2_1_plus_x_prec_round_assign(20, Nearest), Less);
756 /// assert_eq!(x.to_string(), "3.4594307");
757 /// ```
758 #[inline]
759 pub fn log_base_2_1_plus_x_prec_round_assign(
760 &mut self,
761 prec: u64,
762 rm: RoundingMode,
763 ) -> Ordering {
764 let (result, o) = core::mem::take(self).log_base_2_1_plus_x_prec_round(prec, rm);
765 *self = result;
766 o
767 }
768
769 /// Computes $\log_2(1+x)$, where $x$ is a [`Float`], in place, rounding the result to the
770 /// nearest value of the specified precision. An [`Ordering`] is returned, indicating whether
771 /// the rounded value is less than, equal to, or greater than the exact value. Although `NaN`s
772 /// are not comparable to any [`Float`], whenever this function sets the [`Float`] to `NaN` it
773 /// also returns `Equal`.
774 ///
775 /// $\log_2(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, the [`Float`] is set to `NaN`.
776 ///
777 /// If the result is equidistant from two [`Float`]s with the specified precision, the [`Float`]
778 /// with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a description of
779 /// the `Nearest` rounding mode.
780 ///
781 /// $$
782 /// x \gets \log_2(1+x)+\varepsilon.
783 /// $$
784 /// - If $\log_2(1+x)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to
785 /// be 0.
786 /// - If $\log_2(1+x)$ is finite and nonzero, then $|\varepsilon| \leq 2^{\lfloor\log_2
787 /// |\log_2(1+x)|\rfloor-p}$.
788 ///
789 /// If the output has a precision, it is `prec`.
790 ///
791 /// See the [`Float::log_base_2_1_plus_x_prec`] documentation for information on special cases,
792 /// overflow, and underflow.
793 ///
794 /// If you want to use a rounding mode other than `Nearest`, consider using
795 /// [`Float::log_base_2_1_plus_x_prec_round_assign`] instead. If you know that your target
796 /// precision is the precision of the input, consider using
797 /// [`Float::log_base_2_1_plus_x_assign`] instead.
798 ///
799 /// # Worst-case complexity
800 /// $T(n, m) = O(n (\log n)^2 \log\log n + m)$
801 ///
802 /// $M(n, m) = O(n \log n + m)$
803 ///
804 /// where $T$ is time, $M$ is additional memory, $n$ is `prec`, and $m$ is
805 /// `self.significant_bits()`.
806 ///
807 /// # Panics
808 /// Panics if `prec` is zero.
809 ///
810 /// # Examples
811 /// ```
812 /// use malachite_float::Float;
813 /// use std::cmp::Ordering::*;
814 ///
815 /// let mut x = Float::from_unsigned_prec(10u32, 100).0;
816 /// assert_eq!(x.log_base_2_1_plus_x_prec_assign(5), Greater);
817 /// assert_eq!(x.to_string(), "3.50");
818 ///
819 /// let mut x = Float::from_unsigned_prec(10u32, 100).0;
820 /// assert_eq!(x.log_base_2_1_plus_x_prec_assign(20), Less);
821 /// assert_eq!(x.to_string(), "3.4594307");
822 /// ```
823 #[inline]
824 pub fn log_base_2_1_plus_x_prec_assign(&mut self, prec: u64) -> Ordering {
825 self.log_base_2_1_plus_x_prec_round_assign(prec, Nearest)
826 }
827
828 /// Computes $\log_2(1+x)$, where $x$ is a [`Float`], in place, rounding the result with the
829 /// specified rounding mode. An [`Ordering`] is returned, indicating whether the rounded value
830 /// is less than, equal to, or greater than the exact value. Although `NaN`s are not comparable
831 /// to any [`Float`], whenever this function sets the [`Float`] to `NaN` it also returns
832 /// `Equal`.
833 ///
834 /// $\log_2(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, the [`Float`] is set to `NaN`.
835 ///
836 /// The precision of the output is the precision of the input. See [`RoundingMode`] for a
837 /// description of the possible rounding modes.
838 ///
839 /// $$
840 /// x \gets \log_2(1+x)+\varepsilon.
841 /// $$
842 /// - If $\log_2(1+x)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to
843 /// be 0.
844 /// - If $\log_2(1+x)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
845 /// 2^{\lfloor\log_2 |\log_2(1+x)|\rfloor-p+1}$, where $p$ is the precision of the input.
846 /// - If $\log_2(1+x)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
847 /// 2^{\lfloor\log_2 |\log_2(1+x)|\rfloor-p}$, where $p$ is the precision of the input.
848 ///
849 /// If the output has a precision, it is the precision of the input.
850 ///
851 /// See the [`Float::log_base_2_1_plus_x_round`] documentation for information on special cases,
852 /// overflow, and underflow.
853 ///
854 /// If you want to specify an output precision, consider using
855 /// [`Float::log_base_2_1_plus_x_prec_round_assign`] instead. If you know you'll be using the
856 /// `Nearest` rounding mode, consider using [`Float::log_base_2_1_plus_x_assign`] instead.
857 ///
858 /// # Worst-case complexity
859 /// $T(n) = O(n (\log n)^2 \log\log n)$
860 ///
861 /// $M(n) = O(n \log n)$
862 ///
863 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`.
864 ///
865 /// # Panics
866 /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input
867 /// precision. (The result is exactly representable only when the input is `NaN`, infinite,
868 /// zero, $-1$, less than $-1$, or a value for which $1+x$ is a power of 2 whose base-2
869 /// logarithm is representable with the given precision.)
870 ///
871 /// # Examples
872 /// ```
873 /// use malachite_base::rounding_modes::RoundingMode::*;
874 /// use malachite_float::Float;
875 /// use std::cmp::Ordering::*;
876 ///
877 /// let mut x = Float::from_unsigned_prec(10u32, 100).0;
878 /// assert_eq!(x.log_base_2_1_plus_x_round_assign(Floor), Less);
879 /// assert_eq!(x.to_string(), "3.4594316186372972561993630467247");
880 ///
881 /// let mut x = Float::from_unsigned_prec(10u32, 100).0;
882 /// assert_eq!(x.log_base_2_1_plus_x_round_assign(Ceiling), Greater);
883 /// assert_eq!(x.to_string(), "3.4594316186372972561993630467279");
884 ///
885 /// let mut x = Float::from_unsigned_prec(10u32, 100).0;
886 /// assert_eq!(x.log_base_2_1_plus_x_round_assign(Nearest), Less);
887 /// assert_eq!(x.to_string(), "3.4594316186372972561993630467247");
888 /// ```
889 #[inline]
890 pub fn log_base_2_1_plus_x_round_assign(&mut self, rm: RoundingMode) -> Ordering {
891 let prec = self.significant_bits();
892 self.log_base_2_1_plus_x_prec_round_assign(prec, rm)
893 }
894}
895
896impl LogBase2Of1PlusX for Float {
897 type Output = Self;
898
899 /// Computes $\log_2(1+x)$, where $x$ is a [`Float`], taking the [`Float`] by value.
900 ///
901 /// If the output has a precision, it is the precision of the input. If the result is
902 /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in
903 /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
904 /// rounding mode.
905 ///
906 /// $\log_2(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, `NaN` is returned.
907 ///
908 /// $$
909 /// f(x) = \log_2(1+x)+\varepsilon.
910 /// $$
911 /// - If $\log_2(1+x)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to
912 /// be 0.
913 /// - If $\log_2(1+x)$ is finite and nonzero, then $|\varepsilon| \leq 2^{\lfloor\log_2
914 /// |\log_2(1+x)|\rfloor-p}$, where $p$ is the precision of the input.
915 ///
916 /// Special cases:
917 /// - $f(\text{NaN})=\text{NaN}$
918 /// - $f(\infty)=\infty$
919 /// - $f(-\infty)=\text{NaN}$
920 /// - $f(\pm0.0)=\pm0.0$
921 /// - $f(-1)=-\infty$
922 /// - $f(x)=\text{NaN}$ for $x<-1$
923 /// - $f(x)=k$ when $1+x=2^k$. The result is the integer $k$ (subject to rounding at the input
924 /// precision $p$, and exact iff $k$ is representable with precision $p$). This covers $x$ a
925 /// power of 2 minus 1 (e.g. $x=1\to1$, $x=3\to2$) and negative $x$ such as $x=-1/2\to-1$ and
926 /// $x=-3/4\to-2$.
927 ///
928 /// Neither overflow nor underflow is possible.
929 ///
930 /// If you want to use a rounding mode other than `Nearest`, consider using
931 /// [`Float::log_base_2_1_plus_x_round`] instead. If you want to specify the output precision,
932 /// consider using [`Float::log_base_2_1_plus_x_prec`]. If you want both of these things,
933 /// consider using [`Float::log_base_2_1_plus_x_prec_round`].
934 ///
935 /// # Worst-case complexity
936 /// $T(n) = O(n (\log n)^2 \log\log n)$
937 ///
938 /// $M(n) = O(n \log n)$
939 ///
940 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`.
941 ///
942 /// # Examples
943 /// ```
944 /// use malachite_base::num::arithmetic::traits::LogBase2Of1PlusX;
945 /// use malachite_base::num::basic::traits::{
946 /// Infinity, NaN, NegativeInfinity, NegativeOne, One,
947 /// };
948 /// use malachite_float::Float;
949 ///
950 /// assert!(Float::NAN.log_base_2_1_plus_x().is_nan());
951 /// assert_eq!(Float::INFINITY.log_base_2_1_plus_x(), Float::INFINITY);
952 /// assert!(Float::NEGATIVE_INFINITY.log_base_2_1_plus_x().is_nan());
953 /// assert_eq!(Float::ONE.log_base_2_1_plus_x().to_string(), "1.0");
954 /// assert_eq!(
955 /// Float::from_unsigned_prec(10u32, 100)
956 /// .0
957 /// .log_base_2_1_plus_x()
958 /// .to_string(),
959 /// "3.4594316186372972561993630467247"
960 /// );
961 /// assert_eq!(
962 /// Float::NEGATIVE_ONE.log_base_2_1_plus_x(),
963 /// Float::NEGATIVE_INFINITY
964 /// );
965 /// assert!(
966 /// Float::from_signed_prec(-10, 100)
967 /// .0
968 /// .log_base_2_1_plus_x()
969 /// .is_nan()
970 /// );
971 /// ```
972 #[inline]
973 fn log_base_2_1_plus_x(self) -> Self {
974 let prec = self.significant_bits();
975 self.log_base_2_1_plus_x_prec_round(prec, Nearest).0
976 }
977}
978
979impl LogBase2Of1PlusX for &Float {
980 type Output = Float;
981
982 /// Computes $\log_2(1+x)$, where $x$ is a [`Float`], taking the [`Float`] by reference.
983 ///
984 /// If the output has a precision, it is the precision of the input. If the result is
985 /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in
986 /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
987 /// rounding mode.
988 ///
989 /// $\log_2(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, `NaN` is returned.
990 ///
991 /// $$
992 /// f(x) = \log_2(1+x)+\varepsilon.
993 /// $$
994 /// - If $\log_2(1+x)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to
995 /// be 0.
996 /// - If $\log_2(1+x)$ is finite and nonzero, then $|\varepsilon| \leq 2^{\lfloor\log_2
997 /// |\log_2(1+x)|\rfloor-p}$, where $p$ is the precision of the input.
998 ///
999 /// Special cases:
1000 /// - $f(\text{NaN})=\text{NaN}$
1001 /// - $f(\infty)=\infty$
1002 /// - $f(-\infty)=\text{NaN}$
1003 /// - $f(\pm0.0)=\pm0.0$
1004 /// - $f(-1)=-\infty$
1005 /// - $f(x)=\text{NaN}$ for $x<-1$
1006 /// - $f(x)=k$ when $1+x=2^k$. The result is the integer $k$ (subject to rounding at the input
1007 /// precision $p$, and exact iff $k$ is representable with precision $p$). This covers $x$ a
1008 /// power of 2 minus 1 (e.g. $x=1\to1$, $x=3\to2$) and negative $x$ such as $x=-1/2\to-1$ and
1009 /// $x=-3/4\to-2$.
1010 ///
1011 /// Neither overflow nor underflow is possible.
1012 ///
1013 /// If you want to use a rounding mode other than `Nearest`, consider using
1014 /// [`Float::log_base_2_1_plus_x_round_ref`] instead. If you want to specify the output
1015 /// precision, consider using [`Float::log_base_2_1_plus_x_prec_ref`]. If you want both of these
1016 /// things, consider using [`Float::log_base_2_1_plus_x_prec_round_ref`].
1017 ///
1018 /// # Worst-case complexity
1019 /// $T(n) = O(n (\log n)^2 \log\log n)$
1020 ///
1021 /// $M(n) = O(n \log n)$
1022 ///
1023 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`.
1024 ///
1025 /// # Examples
1026 /// ```
1027 /// use malachite_base::num::arithmetic::traits::LogBase2Of1PlusX;
1028 /// use malachite_base::num::basic::traits::{
1029 /// Infinity, NaN, NegativeInfinity, NegativeOne, One,
1030 /// };
1031 /// use malachite_float::Float;
1032 ///
1033 /// assert!((&Float::NAN).log_base_2_1_plus_x().is_nan());
1034 /// assert_eq!((&Float::INFINITY).log_base_2_1_plus_x(), Float::INFINITY);
1035 /// assert!((&Float::NEGATIVE_INFINITY).log_base_2_1_plus_x().is_nan());
1036 /// assert_eq!((&Float::ONE).log_base_2_1_plus_x().to_string(), "1.0");
1037 /// assert_eq!(
1038 /// (&Float::from_unsigned_prec(10u32, 100).0)
1039 /// .log_base_2_1_plus_x()
1040 /// .to_string(),
1041 /// "3.4594316186372972561993630467247"
1042 /// );
1043 /// assert_eq!(
1044 /// (&Float::NEGATIVE_ONE).log_base_2_1_plus_x(),
1045 /// Float::NEGATIVE_INFINITY
1046 /// );
1047 /// assert!(
1048 /// (&Float::from_signed_prec(-10, 100).0)
1049 /// .log_base_2_1_plus_x()
1050 /// .is_nan()
1051 /// );
1052 /// ```
1053 #[inline]
1054 fn log_base_2_1_plus_x(self) -> Float {
1055 let prec = self.significant_bits();
1056 self.log_base_2_1_plus_x_prec_round_ref(prec, Nearest).0
1057 }
1058}
1059
1060impl LogBase2Of1PlusXAssign for Float {
1061 /// Computes $\log_2(1+x)$, where $x$ is a [`Float`], in place.
1062 ///
1063 /// If the output has a precision, it is the precision of the input. If the result is
1064 /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in
1065 /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
1066 /// rounding mode.
1067 ///
1068 /// $\log_2(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, the [`Float`] is set to `NaN`.
1069 ///
1070 /// $$
1071 /// x \gets \log_2(1+x)+\varepsilon.
1072 /// $$
1073 /// - If $\log_2(1+x)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to
1074 /// be 0.
1075 /// - If $\log_2(1+x)$ is finite and nonzero, then $|\varepsilon| \leq 2^{\lfloor\log_2
1076 /// |\log_2(1+x)|\rfloor-p}$, where $p$ is the precision of the input.
1077 ///
1078 /// See the [`Float::log_base_2_1_plus_x`] documentation for information on special cases,
1079 /// overflow, and underflow.
1080 ///
1081 /// If you want to use a rounding mode other than `Nearest`, consider using
1082 /// [`Float::log_base_2_1_plus_x_round_assign`] instead. If you want to specify the output
1083 /// precision, consider using [`Float::log_base_2_1_plus_x_prec_assign`]. If you want both of
1084 /// these things, consider using [`Float::log_base_2_1_plus_x_prec_round_assign`].
1085 ///
1086 /// # Worst-case complexity
1087 /// $T(n) = O(n (\log n)^2 \log\log n)$
1088 ///
1089 /// $M(n) = O(n \log n)$
1090 ///
1091 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`.
1092 ///
1093 /// # Examples
1094 /// ```
1095 /// use malachite_base::num::arithmetic::traits::LogBase2Of1PlusXAssign;
1096 /// use malachite_base::num::basic::traits::{
1097 /// Infinity, NaN, NegativeInfinity, NegativeOne, One,
1098 /// };
1099 /// use malachite_float::Float;
1100 ///
1101 /// let mut x = Float::NAN;
1102 /// x.log_base_2_1_plus_x_assign();
1103 /// assert!(x.is_nan());
1104 ///
1105 /// let mut x = Float::INFINITY;
1106 /// x.log_base_2_1_plus_x_assign();
1107 /// assert_eq!(x, Float::INFINITY);
1108 ///
1109 /// let mut x = Float::NEGATIVE_INFINITY;
1110 /// x.log_base_2_1_plus_x_assign();
1111 /// assert!(x.is_nan());
1112 ///
1113 /// let mut x = Float::ONE;
1114 /// x.log_base_2_1_plus_x_assign();
1115 /// assert_eq!(x.to_string(), "1.0");
1116 ///
1117 /// let mut x = Float::from_unsigned_prec(10u32, 100).0;
1118 /// x.log_base_2_1_plus_x_assign();
1119 /// assert_eq!(x.to_string(), "3.4594316186372972561993630467247");
1120 ///
1121 /// let mut x = Float::NEGATIVE_ONE;
1122 /// x.log_base_2_1_plus_x_assign();
1123 /// assert_eq!(x, Float::NEGATIVE_INFINITY);
1124 ///
1125 /// let mut x = Float::from_signed_prec(-10, 100).0;
1126 /// x.log_base_2_1_plus_x_assign();
1127 /// assert!(x.is_nan());
1128 /// ```
1129 #[inline]
1130 fn log_base_2_1_plus_x_assign(&mut self) {
1131 let prec = self.significant_bits();
1132 self.log_base_2_1_plus_x_prec_round_assign(prec, Nearest);
1133 }
1134}
1135
1136/// Computes the base-2 logarithm of one plus a primitive float, $\log_2(1+x)$. Using this function
1137/// is more accurate than computing `(1 + x).log2()`, both because $1+x$ may not be representable as
1138/// a primitive float and because the standard library's `log2` is not always correctly rounded.
1139///
1140/// $\log_2(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, `NaN` is returned.
1141///
1142/// $$
1143/// f(x) = \log_2(1+x)+\varepsilon.
1144/// $$
1145/// - If $\log_2(1+x)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
1146/// - If $\log_2(1+x)$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2
1147/// |\log_2(1+x)|\rfloor-p}$, where $p$ is precision of the output (typically 24 if `T` is a
1148/// [`f32`] and 53 if `T` is a [`f64`], but less if the output is subnormal).
1149///
1150/// Special cases:
1151/// - $f(\text{NaN})=\text{NaN}$
1152/// - $f(\infty)=\infty$
1153/// - $f(-\infty)=\text{NaN}$
1154/// - $f(\pm0.0)=\pm0.0$
1155/// - $f(-1.0)=-\infty$
1156/// - $f(x)=\text{NaN}$ for $x<-1$
1157///
1158/// Neither overflow nor underflow is possible.
1159///
1160/// # Worst-case complexity
1161/// Constant time and additional memory.
1162///
1163/// # Examples
1164/// ```
1165/// use malachite_base::num::basic::traits::NegativeInfinity;
1166/// use malachite_base::num::float::NiceFloat;
1167/// use malachite_float::float::arithmetic::log_base_2_1_plus_x::*;
1168///
1169/// assert!(primitive_float_log_base_2_1_plus_x(f32::NAN).is_nan());
1170/// assert_eq!(
1171/// NiceFloat(primitive_float_log_base_2_1_plus_x(f32::INFINITY)),
1172/// NiceFloat(f32::INFINITY)
1173/// );
1174/// assert!(primitive_float_log_base_2_1_plus_x(f32::NEGATIVE_INFINITY).is_nan());
1175/// assert_eq!(
1176/// NiceFloat(primitive_float_log_base_2_1_plus_x(-1.0f32)),
1177/// NiceFloat(f32::NEGATIVE_INFINITY)
1178/// );
1179/// assert!(primitive_float_log_base_2_1_plus_x(-2.0f32).is_nan());
1180/// assert_eq!(
1181/// NiceFloat(primitive_float_log_base_2_1_plus_x(1.0f32)),
1182/// NiceFloat(1.0)
1183/// );
1184/// assert_eq!(
1185/// NiceFloat(primitive_float_log_base_2_1_plus_x(7.0f32)),
1186/// NiceFloat(3.0)
1187/// );
1188/// ```
1189#[inline]
1190#[allow(clippy::type_repetition_in_bounds)]
1191pub fn primitive_float_log_base_2_1_plus_x<T: PrimitiveFloat>(x: T) -> T
1192where
1193 Float: From<T> + PartialOrd<T>,
1194 for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
1195{
1196 emulate_float_to_float_fn(Float::log_base_2_1_plus_x_prec, x)
1197}