malachite_float/arithmetic/log_base_2.rs
1// Copyright © 2026 Mikhail Hogrefe
2//
3// Uses code adopted from the GNU MPFR Library.
4//
5// Copyright 2001-2026 Free Software Foundation, Inc.
6//
7// Contributed by the Pascaline and Caramba projects, INRIA.
8//
9// This file is part of Malachite.
10//
11// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
12// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
13// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
14
15use crate::InnerFloat::{Finite, Infinity, NaN, Zero};
16use crate::arithmetic::round_near_x::float_round_near_x;
17use crate::basic::extended::ExtendedFloat;
18use crate::{
19 Float, emulate_float_to_float_fn, emulate_rational_to_float_fn, float_either_zero,
20 float_infinity, float_nan, float_negative_infinity,
21};
22use core::cmp::Ordering::{self, *};
23use malachite_base::num::arithmetic::traits::{
24 CeilingLogBase2, CheckedLogBase2, IsPowerOf2, LogBase2, LogBase2Assign, PowerOf2, Sign,
25};
26use malachite_base::num::basic::floats::PrimitiveFloat;
27use malachite_base::num::basic::integers::PrimitiveInt;
28use malachite_base::num::basic::traits::{One, Zero as ZeroTrait};
29use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom};
30use malachite_base::num::logic::traits::SignificantBits;
31use malachite_base::rounding_modes::RoundingMode::{self, *};
32use malachite_nz::natural::arithmetic::float_extras::float_can_round;
33use malachite_nz::platform::Limb;
34use malachite_q::Rational;
35
36// The computation of log_base_2(x) is done by log_base_2(x) = ln(x) / ln(2).
37//
38// This is mpfr_log2 from log2.c, MPFR 4.3.0, where the input is finite, nonzero, and positive.
39fn log_base_2_prec_round_normal(x: &Float, prec: u64, rm: RoundingMode) -> (Float, Ordering) {
40 // If x is 1, the result is 0.
41 if *x == 1u32 {
42 return (Float::ZERO, Equal);
43 }
44 // If x is 2^k, log_base_2(x) is exact (though possibly subject to rounding at the target
45 // precision).
46 if x.is_power_of_2() {
47 return Float::from_signed_prec_round(i64::from(x.get_exponent().unwrap()) - 1, prec, rm);
48 }
49 // The result is never exactly representable for other inputs.
50 assert_ne!(rm, Exact, "Inexact log_base_2");
51 // Compute the precision of the intermediary variable: the optimal number of bits, see
52 // algorithms.tex.
53 let mut working_prec = prec + 3 + prec.ceiling_log_base_2();
54 let mut increment = Limb::WIDTH;
55 loop {
56 // ln(x) / ln(2)
57 let t = x
58 .ln_prec_ref(working_prec)
59 .0
60 .div_prec(Float::ln_2_prec(working_prec).0, working_prec)
61 .0;
62 // Estimation of the error.
63 if float_can_round(t.significand_ref().unwrap(), working_prec - 3, prec, rm) {
64 return Float::from_float_prec_round(t, prec, rm);
65 }
66 // Increase the precision.
67 working_prec += increment;
68 increment = working_prec >> 1;
69 }
70}
71
72// Computes `log_2(1 + eps)` for a small nonzero [`Rational`] `eps` (`x - 1`, where `x` is near 1).
73// The result is near zero, so unlike the near-a-larger-power case it must be computed directly
74// rather than rounded near an integer; a Ziv loop over a [`Float`] approximation of `eps` does so
75// without the catastrophic cancellation that `ln(x)` would suffer for `x` near 1.
76fn log_base_2_rational_near_one(eps: &Rational, prec: u64, rm: RoundingMode) -> (Float, Ordering) {
77 let mut working_prec = prec + 3 + prec.ceiling_log_base_2();
78 let mut increment = Limb::WIDTH;
79 loop {
80 // log_2(1 + eps), via a Float approximation of eps. The error comes from `eps_float`
81 // approximating `eps` (below an ulp) and from the rounding in `log_base_2_1_plus_x` (below
82 // an ulp), so a few ulps of slack suffice.
83 let eps_float = Float::from_rational_prec_ref(eps, working_prec).0;
84 let off = eps_float.log_base_2_1_plus_x_prec(working_prec).0;
85 if float_can_round(off.significand_ref().unwrap(), working_prec - 3, prec, rm) {
86 return Float::from_float_prec_round(off, prec, rm);
87 }
88 working_prec += increment;
89 increment = working_prec >> 1;
90 }
91}
92
93// If `x` is close enough to a power of 2 that the general Ziv loop would need a precision
94// proportional to the distance (potentially exhausting memory), returns the correctly-rounded
95// `log_2(x)`; otherwise returns `None`. `x` must be positive and not a power of 2.
96//
97// `log_2(x) = k + log_2(x / 2^k)` for the nearest power of 2, `2^k`. When `x` is very close to
98// `2^k` the offset `log_2(x / 2^k)` is tiny: for `k != 0` the result is `k` nudged by a fraction of
99// an ulp, which `float_round_near_x` rounds directly (returning `None` when the offset is not
100// sub-ulp, so the general loop — which then converges quickly — takes over); for `k == 0` (`x`
101// near 1) the result is the tiny offset itself.
102fn log_base_2_rational_near_power_of_2(
103 x: &Rational,
104 prec: u64,
105 rm: RoundingMode,
106) -> Option<(Float, Ordering)> {
107 // 2^m <= x < 2^(m + 1)
108 let m = x.floor_log_base_2_abs();
109 let pow_lo = Rational::power_of_2(m);
110 let pow_hi = Rational::power_of_2(m + 1);
111 // eps = x / 2^k - 1 for the nearer of the two surrounding powers of 2, 2^k.
112 let dist_lo = x - &pow_lo;
113 let dist_hi = &pow_hi - x;
114 let (k, eps) = if dist_lo <= dist_hi {
115 (m, dist_lo / pow_lo)
116 } else {
117 (m + 1, -(dist_hi / pow_hi))
118 };
119 if k == 0 {
120 // x is near 1, so log_2(x) = log_2(1 + eps) is near zero.
121 return Some(log_base_2_rational_near_one(&eps, prec, rm));
122 }
123 // eps is nonzero since x is not a power of 2.
124 let eps_exp = eps.floor_log_base_2_abs();
125 let k_float = Float::from_signed_prec(k, k.unsigned_abs().significant_bits()).0;
126 let exp_k = i64::from(k_float.get_exponent().unwrap());
127 // |log_2(1 + eps)| < 3|eps| < 2^(eps_exp + 3), so passing err = exp_k - eps_exp - 3 to
128 // `float_round_near_x` (which requires |offset| < 2^(exp_k - err)) is sound.
129 let err = exp_k - eps_exp - 3;
130 if err <= 0 {
131 return None;
132 }
133 // The offset moves the magnitude up (away from zero) iff it has the same sign as k.
134 let dir = (eps > 0) == (k > 0);
135 float_round_near_x(&k_float, u64::exact_from(err), dir, prec, rm)
136}
137
138// The computation of log_base_2(x) is done by log_base_2(x) = ln(x) / ln(2). `ln_rational_prec`
139// handles inputs whose magnitudes are outside the representable range of `Float`; the result of the
140// division has greater magnitude than the result of `ln_rational_prec`, but only by a factor of
141// 1/ln(2), so the division cannot overflow or underflow if the `ln` didn't.
142fn log_base_2_rational_prec_round_helper(
143 x: &Rational,
144 prec: u64,
145 rm: RoundingMode,
146) -> (Float, Ordering) {
147 // When x is extremely close to a power of 2, log_2(x) is extremely close to an integer, and the
148 // Ziv loop below would need a precision proportional to the distance to round it. Handle that
149 // case separately.
150 if let Some(result) = log_base_2_rational_near_power_of_2(x, prec, rm) {
151 return result;
152 }
153 let mut working_prec = prec + 3 + prec.ceiling_log_base_2();
154 let mut increment = Limb::WIDTH;
155 loop {
156 // ln(x) / ln(2)
157 let t = Float::ln_rational_prec_ref(x, working_prec)
158 .0
159 .div_prec(Float::ln_2_prec(working_prec).0, working_prec)
160 .0;
161 // Estimation of the error.
162 if float_can_round(t.significand_ref().unwrap(), working_prec - 3, prec, rm) {
163 return Float::from_float_prec_round(t, prec, rm);
164 }
165 // Increase the precision.
166 working_prec += increment;
167 increment = working_prec >> 1;
168 }
169}
170
171// Computes `log_2(r)` as an `ExtendedFloat`, accurate to within 2 ulps of `prec` bits. `r` must be
172// positive and not equal to 1.
173//
174// The result is kept in the extended exponent range so that an `r` extremely close to 1 -- where
175// `log_2(r)` is tiny and would underflow an ordinary `Float` (its value-exponent reaches `-2^63`,
176// far below `MIN_EXPONENT = -(2^30 - 1)`) -- is represented faithfully rather than flushed to zero.
177// This lets the logarithm-with-a-rational-base functions divide two such logs and clamp only once,
178// at the very end, rather than losing the operand entirely.
179//
180// For `r` not pathologically near 1, the ordinary `log_2(r)` is a normal `Float`, correctly rounded
181// (at most 1/2 ulp), and is simply wrapped. When `r` is within about `2^(-2^30)` of 1, `log_2(r) =
182// log_2(1 + y)` with `y = r - 1`, and `log_2(1 + y) = y / ln 2 + O(y^2)`; here `|y| < 2^(-2^30)` is
183// far smaller than `2^(-prec)`, so the `O(y^2)` term is below an ulp and `y / ln 2` (computed in
184// the extended range, where `y`'s exponent fits in the `i64`) is accurate to within 2 ulps (1/2
185// from the conversion of `y`, 1/2 from the division, the rest from the dropped term).
186pub(crate) fn extended_log_base_2_of_rational(r: &Rational, prec: u64) -> ExtendedFloat {
187 // `log_2(r)` underflows an ordinary `Float` only when `r` is within roughly `2^(-2^30)` of 1.
188 // Switch to the linear approximation a couple of exponents before that boundary; the ordinary
189 // path is then guaranteed not to underflow, and the linear path is valid well beyond it.
190 let y = r - Rational::ONE;
191 if y.floor_log_base_2_abs() <= i64::from(Float::MIN_EXPONENT) + 1 {
192 let y_ext = ExtendedFloat::from_rational_prec_round_ref(&y, prec, Nearest).0;
193 let ln_2 = ExtendedFloat::from(Float::ln_2_prec(prec).0);
194 y_ext.div_prec_val_ref(&ln_2, prec).0
195 } else {
196 ExtendedFloat::from(Float::log_base_2_rational_prec_ref(r, prec).0)
197 }
198}
199
200impl Float {
201 /// Computes $\log_2 x$, where $x$ is a [`Float`], rounding the result to the specified
202 /// precision and with the specified rounding mode. The [`Float`] is taken by value. An
203 /// [`Ordering`] is also returned, indicating whether the rounded value is less than, equal to,
204 /// or greater than the exact value. Although `NaN`s are not comparable to any [`Float`],
205 /// whenever this function returns a `NaN` it also returns `Equal`.
206 ///
207 /// The base-2 logarithm of any nonzero negative number is `NaN`.
208 ///
209 /// See [`RoundingMode`] for a description of the possible rounding modes.
210 ///
211 /// $$
212 /// f(x,p,m) = \log_2 x+\varepsilon.
213 /// $$
214 /// - If $\log_2 x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be
215 /// 0.
216 /// - If $\log_2 x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
217 /// 2^{\lfloor\log_2 |\log_2 x|\rfloor-p+1}$.
218 /// - If $\log_2 x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
219 /// 2^{\lfloor\log_2 |\log_2 x|\rfloor-p}$.
220 ///
221 /// If the output has a precision, it is `prec`.
222 ///
223 /// Special cases:
224 /// - $f(\text{NaN},p,m)=\text{NaN}$
225 /// - $f(\infty,p,m)=\infty$
226 /// - $f(-\infty,p,m)=\text{NaN}$
227 /// - $f(\pm0.0,p,m)=-\infty$
228 /// - $f(1.0,p,m)=0.0$, and the result is exact
229 /// - $f(2^k,p,m)=k$, rounded to precision $p$; the result is exact if and only if $k$ is
230 /// representable with precision $p$
231 /// - $f(x,p,m)=\text{NaN}$ for $x<0$
232 ///
233 /// Neither overflow nor underflow is possible.
234 ///
235 /// If you know you'll be using `Nearest`, consider using [`Float::log_base_2_prec`] instead. If
236 /// you know that your target precision is the precision of the input, consider using
237 /// [`Float::log_base_2_round`] instead. If both of these things are true, consider using
238 /// [`Float::log_base_2`] instead.
239 ///
240 /// # Worst-case complexity
241 /// $T(n) = O(n (\log n)^2 \log\log n)$
242 ///
243 /// $M(n) = O(n (\log n)^2)$
244 ///
245 /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
246 ///
247 /// # Panics
248 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
249 /// with the given precision. (The result is exactly representable if and only if the input is
250 /// `NaN`, infinite, zero, equal to 1, or a power of 2 whose base-2 logarithm is representable
251 /// with the given precision.)
252 ///
253 /// # Examples
254 /// ```
255 /// use malachite_base::rounding_modes::RoundingMode::*;
256 /// use malachite_float::Float;
257 /// use std::cmp::Ordering::*;
258 ///
259 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
260 /// .0
261 /// .log_base_2_prec_round(5, Floor);
262 /// assert_eq!(log.to_string(), "3.2");
263 /// assert_eq!(o, Less);
264 ///
265 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
266 /// .0
267 /// .log_base_2_prec_round(5, Ceiling);
268 /// assert_eq!(log.to_string(), "3.4");
269 /// assert_eq!(o, Greater);
270 ///
271 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
272 /// .0
273 /// .log_base_2_prec_round(5, Nearest);
274 /// assert_eq!(log.to_string(), "3.4");
275 /// assert_eq!(o, Greater);
276 ///
277 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
278 /// .0
279 /// .log_base_2_prec_round(20, Floor);
280 /// assert_eq!(log.to_string(), "3.321926");
281 /// assert_eq!(o, Less);
282 ///
283 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
284 /// .0
285 /// .log_base_2_prec_round(20, Ceiling);
286 /// assert_eq!(log.to_string(), "3.32193");
287 /// assert_eq!(o, Greater);
288 ///
289 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
290 /// .0
291 /// .log_base_2_prec_round(20, Nearest);
292 /// assert_eq!(log.to_string(), "3.32193");
293 /// assert_eq!(o, Greater);
294 /// ```
295 #[inline]
296 pub fn log_base_2_prec_round(self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
297 assert_ne!(prec, 0);
298 match self {
299 Self(NaN | Infinity { sign: false } | Finite { sign: false, .. }) => {
300 (float_nan!(), Equal)
301 }
302 float_either_zero!() => (float_negative_infinity!(), Equal),
303 float_infinity!() => (float_infinity!(), Equal),
304 _ => log_base_2_prec_round_normal(&self, prec, rm),
305 }
306 }
307
308 /// Computes $\log_2 x$, where $x$ is a [`Float`], rounding the result to the specified
309 /// precision and with the specified rounding mode. The [`Float`] is taken by reference. An
310 /// [`Ordering`] is also returned, indicating whether the rounded value is less than, equal to,
311 /// or greater than the exact value. Although `NaN`s are not comparable to any [`Float`],
312 /// whenever this function returns a `NaN` it also returns `Equal`.
313 ///
314 /// The base-2 logarithm of any nonzero negative number is `NaN`.
315 ///
316 /// See [`RoundingMode`] for a description of the possible rounding modes.
317 ///
318 /// $$
319 /// f(x,p,m) = \log_2 x+\varepsilon.
320 /// $$
321 /// - If $\log_2 x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be
322 /// 0.
323 /// - If $\log_2 x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
324 /// 2^{\lfloor\log_2 |\log_2 x|\rfloor-p+1}$.
325 /// - If $\log_2 x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
326 /// 2^{\lfloor\log_2 |\log_2 x|\rfloor-p}$.
327 ///
328 /// If the output has a precision, it is `prec`.
329 ///
330 /// Special cases:
331 /// - $f(\text{NaN},p,m)=\text{NaN}$
332 /// - $f(\infty,p,m)=\infty$
333 /// - $f(-\infty,p,m)=\text{NaN}$
334 /// - $f(\pm0.0,p,m)=-\infty$
335 /// - $f(1.0,p,m)=0.0$, and the result is exact
336 /// - $f(2^k,p,m)=k$, rounded to precision $p$; the result is exact if and only if $k$ is
337 /// representable with precision $p$
338 /// - $f(x,p,m)=\text{NaN}$ for $x<0$
339 ///
340 /// Neither overflow nor underflow is possible.
341 ///
342 /// If you know you'll be using `Nearest`, consider using [`Float::log_base_2_prec_ref`]
343 /// instead. If you know that your target precision is the precision of the input, consider
344 /// using [`Float::log_base_2_round_ref`] instead. If both of these things are true, consider
345 /// using `(&Float).log_base_2()` instead.
346 ///
347 /// # Worst-case complexity
348 /// $T(n) = O(n (\log n)^2 \log\log n)$
349 ///
350 /// $M(n) = O(n (\log n)^2)$
351 ///
352 /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
353 ///
354 /// # Panics
355 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
356 /// with the given precision. (The result is exactly representable if and only if the input is
357 /// `NaN`, infinite, zero, equal to 1, or a power of 2 whose base-2 logarithm is representable
358 /// with the given precision.)
359 ///
360 /// # Examples
361 /// ```
362 /// use malachite_base::rounding_modes::RoundingMode::*;
363 /// use malachite_float::Float;
364 /// use std::cmp::Ordering::*;
365 ///
366 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
367 /// .0
368 /// .log_base_2_prec_round_ref(5, Floor);
369 /// assert_eq!(log.to_string(), "3.2");
370 /// assert_eq!(o, Less);
371 ///
372 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
373 /// .0
374 /// .log_base_2_prec_round_ref(5, Ceiling);
375 /// assert_eq!(log.to_string(), "3.4");
376 /// assert_eq!(o, Greater);
377 ///
378 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
379 /// .0
380 /// .log_base_2_prec_round_ref(5, Nearest);
381 /// assert_eq!(log.to_string(), "3.4");
382 /// assert_eq!(o, Greater);
383 ///
384 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
385 /// .0
386 /// .log_base_2_prec_round_ref(20, Floor);
387 /// assert_eq!(log.to_string(), "3.321926");
388 /// assert_eq!(o, Less);
389 ///
390 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
391 /// .0
392 /// .log_base_2_prec_round_ref(20, Ceiling);
393 /// assert_eq!(log.to_string(), "3.32193");
394 /// assert_eq!(o, Greater);
395 ///
396 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
397 /// .0
398 /// .log_base_2_prec_round_ref(20, Nearest);
399 /// assert_eq!(log.to_string(), "3.32193");
400 /// assert_eq!(o, Greater);
401 /// ```
402 #[inline]
403 pub fn log_base_2_prec_round_ref(&self, prec: u64, rm: RoundingMode) -> (Self, Ordering) {
404 assert_ne!(prec, 0);
405 match self {
406 Self(NaN | Infinity { sign: false } | Finite { sign: false, .. }) => {
407 (float_nan!(), Equal)
408 }
409 float_either_zero!() => (float_negative_infinity!(), Equal),
410 float_infinity!() => (float_infinity!(), Equal),
411 _ => log_base_2_prec_round_normal(self, prec, rm),
412 }
413 }
414
415 /// Computes $\log_2 x$, where $x$ is a [`Float`], rounding the result to the nearest value of
416 /// the specified precision. The [`Float`] is taken by value. An [`Ordering`] is also returned,
417 /// indicating whether the rounded value is less than, equal to, or greater than the exact
418 /// value. Although `NaN`s are not comparable to any [`Float`], whenever this function returns a
419 /// `NaN` it also returns `Equal`.
420 ///
421 /// The base-2 logarithm of any nonzero negative number is `NaN`.
422 ///
423 /// If the logarithm is equidistant from two [`Float`]s with the specified precision, the
424 /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
425 /// description of the `Nearest` rounding mode.
426 ///
427 /// $$
428 /// f(x,p) = \log_2 x+\varepsilon.
429 /// $$
430 /// - If $\log_2 x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be
431 /// 0.
432 /// - If $\log_2 x$ is finite and nonzero, then $|\varepsilon| \leq 2^{\lfloor\log_2 |\log_2
433 /// x|\rfloor-p}$.
434 ///
435 /// If the output has a precision, it is `prec`.
436 ///
437 /// Special cases:
438 /// - $f(\text{NaN},p)=\text{NaN}$
439 /// - $f(\infty,p)=\infty$
440 /// - $f(-\infty,p)=\text{NaN}$
441 /// - $f(\pm0.0,p)=-\infty$
442 /// - $f(1.0,p)=0.0$, and the result is exact
443 /// - $f(2^k,p)=k$, rounded to precision $p$; the result is exact if and only if $k$ is
444 /// representable with precision $p$
445 /// - $f(x,p)=\text{NaN}$ for $x<0$
446 ///
447 /// Neither overflow nor underflow is possible.
448 ///
449 /// If you want to use a rounding mode other than `Nearest`, consider using
450 /// [`Float::log_base_2_prec_round`] instead. If you know that your target precision is the
451 /// precision of the input, consider using [`Float::log_base_2`] instead.
452 ///
453 /// # Worst-case complexity
454 /// $T(n) = O(n (\log n)^2 \log\log n)$
455 ///
456 /// $M(n) = O(n (\log n)^2)$
457 ///
458 /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
459 ///
460 /// # Panics
461 /// Panics if `prec` is zero.
462 ///
463 /// # Examples
464 /// ```
465 /// use malachite_float::Float;
466 /// use std::cmp::Ordering::*;
467 ///
468 /// let (log, o) = Float::from_unsigned_prec(10u32, 100).0.log_base_2_prec(5);
469 /// assert_eq!(log.to_string(), "3.4");
470 /// assert_eq!(o, Greater);
471 ///
472 /// let (log, o) = Float::from_unsigned_prec(10u32, 100).0.log_base_2_prec(20);
473 /// assert_eq!(log.to_string(), "3.32193");
474 /// assert_eq!(o, Greater);
475 /// ```
476 #[inline]
477 pub fn log_base_2_prec(self, prec: u64) -> (Self, Ordering) {
478 self.log_base_2_prec_round(prec, Nearest)
479 }
480
481 /// Computes $\log_2 x$, where $x$ is a [`Float`], rounding the result to the nearest value of
482 /// the specified precision. The [`Float`] is taken by reference. An [`Ordering`] is also
483 /// returned, indicating whether the rounded value is less than, equal to, or greater than the
484 /// exact value. Although `NaN`s are not comparable to any [`Float`], whenever this function
485 /// returns a `NaN` it also returns `Equal`.
486 ///
487 /// The base-2 logarithm of any nonzero negative number is `NaN`.
488 ///
489 /// If the logarithm is equidistant from two [`Float`]s with the specified precision, the
490 /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
491 /// description of the `Nearest` rounding mode.
492 ///
493 /// $$
494 /// f(x,p) = \log_2 x+\varepsilon.
495 /// $$
496 /// - If $\log_2 x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be
497 /// 0.
498 /// - If $\log_2 x$ is finite and nonzero, then $|\varepsilon| \leq 2^{\lfloor\log_2 |\log_2
499 /// x|\rfloor-p}$.
500 ///
501 /// If the output has a precision, it is `prec`.
502 ///
503 /// Special cases:
504 /// - $f(\text{NaN},p)=\text{NaN}$
505 /// - $f(\infty,p)=\infty$
506 /// - $f(-\infty,p)=\text{NaN}$
507 /// - $f(\pm0.0,p)=-\infty$
508 /// - $f(1.0,p)=0.0$, and the result is exact
509 /// - $f(2^k,p)=k$, rounded to precision $p$; the result is exact if and only if $k$ is
510 /// representable with precision $p$
511 /// - $f(x,p)=\text{NaN}$ for $x<0$
512 ///
513 /// Neither overflow nor underflow is possible.
514 ///
515 /// If you want to use a rounding mode other than `Nearest`, consider using
516 /// [`Float::log_base_2_prec_round_ref`] instead. If you know that your target precision is the
517 /// precision of the input, consider using `(&Float).log_base_2()` instead.
518 ///
519 /// # Worst-case complexity
520 /// $T(n) = O(n (\log n)^2 \log\log n)$
521 ///
522 /// $M(n) = O(n (\log n)^2)$
523 ///
524 /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
525 ///
526 /// # Panics
527 /// Panics if `prec` is zero.
528 ///
529 /// # Examples
530 /// ```
531 /// use malachite_float::Float;
532 /// use std::cmp::Ordering::*;
533 ///
534 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
535 /// .0
536 /// .log_base_2_prec_ref(5);
537 /// assert_eq!(log.to_string(), "3.4");
538 /// assert_eq!(o, Greater);
539 ///
540 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
541 /// .0
542 /// .log_base_2_prec_ref(20);
543 /// assert_eq!(log.to_string(), "3.32193");
544 /// assert_eq!(o, Greater);
545 /// ```
546 #[inline]
547 pub fn log_base_2_prec_ref(&self, prec: u64) -> (Self, Ordering) {
548 self.log_base_2_prec_round_ref(prec, Nearest)
549 }
550
551 /// Computes $\log_2 x$, where $x$ is a [`Float`], rounding the result with the specified
552 /// rounding mode. The [`Float`] is taken by value. An [`Ordering`] is also returned, indicating
553 /// whether the rounded value is less than, equal to, or greater than the exact value. Although
554 /// `NaN`s are not comparable to any [`Float`], whenever this function returns a `NaN` it also
555 /// returns `Equal`.
556 ///
557 /// The base-2 logarithm of any nonzero negative number is `NaN`.
558 ///
559 /// The precision of the output is the precision of the input. See [`RoundingMode`] for a
560 /// description of the possible rounding modes.
561 ///
562 /// $$
563 /// f(x,m) = \log_2 x+\varepsilon.
564 /// $$
565 /// - If $\log_2 x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be
566 /// 0.
567 /// - If $\log_2 x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
568 /// 2^{\lfloor\log_2 |\log_2 x|\rfloor-p+1}$, where $p$ is the precision of the input.
569 /// - If $\log_2 x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
570 /// 2^{\lfloor\log_2 |\log_2 x|\rfloor-p}$, where $p$ is the precision of the input.
571 ///
572 /// If the output has a precision, it is the precision of the input.
573 ///
574 /// Special cases:
575 /// - $f(\text{NaN},m)=\text{NaN}$
576 /// - $f(\infty,m)=\infty$
577 /// - $f(-\infty,m)=\text{NaN}$
578 /// - $f(\pm0.0,m)=-\infty$
579 /// - $f(1.0,m)=0.0$, and the result is exact
580 /// - $f(2^k,m)=k$, rounded to the precision of the input; the result is exact if and only if
581 /// $k$ is representable with that precision
582 /// - $f(x,m)=\text{NaN}$ for $x<0$
583 ///
584 /// Neither overflow nor underflow is possible.
585 ///
586 /// If you want to specify an output precision, consider using [`Float::log_base_2_prec_round`]
587 /// instead. If you know you'll be using the `Nearest` rounding mode, consider using
588 /// [`Float::log_base_2`] instead.
589 ///
590 /// # Worst-case complexity
591 /// $T(n) = O(n (\log n)^2 \log\log n)$
592 ///
593 /// $M(n) = O(n (\log n)^2)$
594 ///
595 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`.
596 ///
597 /// # Panics
598 /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input
599 /// precision. (The result is exactly representable if and only if the input is `NaN`, infinite,
600 /// zero, equal to 1, or a power of 2 whose base-2 logarithm is representable with the input
601 /// precision.)
602 ///
603 /// # Examples
604 /// ```
605 /// use malachite_base::rounding_modes::RoundingMode::*;
606 /// use malachite_float::Float;
607 /// use std::cmp::Ordering::*;
608 ///
609 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
610 /// .0
611 /// .log_base_2_round(Floor);
612 /// assert_eq!(log.to_string(), "3.321928094887362347870319429487");
613 /// assert_eq!(o, Less);
614 ///
615 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
616 /// .0
617 /// .log_base_2_round(Ceiling);
618 /// assert_eq!(log.to_string(), "3.32192809488736234787031942949");
619 /// assert_eq!(o, Greater);
620 ///
621 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
622 /// .0
623 /// .log_base_2_round(Nearest);
624 /// assert_eq!(log.to_string(), "3.32192809488736234787031942949");
625 /// assert_eq!(o, Greater);
626 /// ```
627 #[inline]
628 pub fn log_base_2_round(self, rm: RoundingMode) -> (Self, Ordering) {
629 let prec = self.significant_bits();
630 self.log_base_2_prec_round(prec, rm)
631 }
632
633 /// Computes $\log_2 x$, where $x$ is a [`Float`], rounding the result with the specified
634 /// rounding mode. The [`Float`] is taken by reference. An [`Ordering`] is also returned,
635 /// indicating whether the rounded value is less than, equal to, or greater than the exact
636 /// value. Although `NaN`s are not comparable to any [`Float`], whenever this function returns a
637 /// `NaN` it also returns `Equal`.
638 ///
639 /// The base-2 logarithm of any nonzero negative number is `NaN`.
640 ///
641 /// The precision of the output is the precision of the input. See [`RoundingMode`] for a
642 /// description of the possible rounding modes.
643 ///
644 /// $$
645 /// f(x,m) = \log_2 x+\varepsilon.
646 /// $$
647 /// - If $\log_2 x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be
648 /// 0.
649 /// - If $\log_2 x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
650 /// 2^{\lfloor\log_2 |\log_2 x|\rfloor-p+1}$, where $p$ is the precision of the input.
651 /// - If $\log_2 x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
652 /// 2^{\lfloor\log_2 |\log_2 x|\rfloor-p}$, where $p$ is the precision of the input.
653 ///
654 /// If the output has a precision, it is the precision of the input.
655 ///
656 /// Special cases:
657 /// - $f(\text{NaN},m)=\text{NaN}$
658 /// - $f(\infty,m)=\infty$
659 /// - $f(-\infty,m)=\text{NaN}$
660 /// - $f(\pm0.0,m)=-\infty$
661 /// - $f(1.0,m)=0.0$, and the result is exact
662 /// - $f(2^k,m)=k$, rounded to the precision of the input; the result is exact if and only if
663 /// $k$ is representable with that precision
664 /// - $f(x,m)=\text{NaN}$ for $x<0$
665 ///
666 /// Neither overflow nor underflow is possible.
667 ///
668 /// If you want to specify an output precision, consider using
669 /// [`Float::log_base_2_prec_round_ref`] instead. If you know you'll be using the `Nearest`
670 /// rounding mode, consider using `(&Float).log_base_2()` instead.
671 ///
672 /// # Worst-case complexity
673 /// $T(n) = O(n (\log n)^2 \log\log n)$
674 ///
675 /// $M(n) = O(n (\log n)^2)$
676 ///
677 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`.
678 ///
679 /// # Panics
680 /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input
681 /// precision. (The result is exactly representable if and only if the input is `NaN`, infinite,
682 /// zero, equal to 1, or a power of 2 whose base-2 logarithm is representable with the input
683 /// precision.)
684 ///
685 /// # Examples
686 /// ```
687 /// use malachite_base::rounding_modes::RoundingMode::*;
688 /// use malachite_float::Float;
689 /// use std::cmp::Ordering::*;
690 ///
691 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
692 /// .0
693 /// .log_base_2_round_ref(Floor);
694 /// assert_eq!(log.to_string(), "3.321928094887362347870319429487");
695 /// assert_eq!(o, Less);
696 ///
697 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
698 /// .0
699 /// .log_base_2_round_ref(Ceiling);
700 /// assert_eq!(log.to_string(), "3.32192809488736234787031942949");
701 /// assert_eq!(o, Greater);
702 ///
703 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
704 /// .0
705 /// .log_base_2_round_ref(Nearest);
706 /// assert_eq!(log.to_string(), "3.32192809488736234787031942949");
707 /// assert_eq!(o, Greater);
708 /// ```
709 #[inline]
710 pub fn log_base_2_round_ref(&self, rm: RoundingMode) -> (Self, Ordering) {
711 let prec = self.significant_bits();
712 self.log_base_2_prec_round_ref(prec, rm)
713 }
714
715 /// Computes $\log_2 x$, where $x$ is a [`Float`], in place, rounding the result to the
716 /// specified precision and with the specified rounding mode. An [`Ordering`] is returned,
717 /// indicating whether the rounded value is less than, equal to, or greater than the exact
718 /// value. Although `NaN`s are not comparable to any [`Float`], whenever this function sets the
719 /// [`Float`] to `NaN` it also returns `Equal`.
720 ///
721 /// The base-2 logarithm of any nonzero negative number is `NaN`.
722 ///
723 /// See [`RoundingMode`] for a description of the possible rounding modes.
724 ///
725 /// $$
726 /// x \gets \log_2 x+\varepsilon.
727 /// $$
728 /// - If $\log_2 x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be
729 /// 0.
730 /// - If $\log_2 x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
731 /// 2^{\lfloor\log_2 |\log_2 x|\rfloor-p+1}$.
732 /// - If $\log_2 x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
733 /// 2^{\lfloor\log_2 |\log_2 x|\rfloor-p}$.
734 ///
735 /// If the output has a precision, it is `prec`.
736 ///
737 /// See the [`Float::log_base_2_prec_round`] documentation for information on special cases,
738 /// overflow, and underflow.
739 ///
740 /// If you know you'll be using `Nearest`, consider using [`Float::log_base_2_prec_assign`]
741 /// instead. If you know that your target precision is the precision of the input, consider
742 /// using [`Float::log_base_2_round_assign`] instead. If both of these things are true, consider
743 /// using [`Float::log_base_2_assign`] instead.
744 ///
745 /// # Worst-case complexity
746 /// $T(n) = O(n (\log n)^2 \log\log n)$
747 ///
748 /// $M(n) = O(n (\log n)^2)$
749 ///
750 /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
751 ///
752 /// # Panics
753 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
754 /// with the given precision. (The result is exactly representable if and only if the input is
755 /// `NaN`, infinite, zero, equal to 1, or a power of 2 whose base-2 logarithm is representable
756 /// with the given precision.)
757 ///
758 /// # Examples
759 /// ```
760 /// use malachite_base::rounding_modes::RoundingMode::*;
761 /// use malachite_float::Float;
762 /// use std::cmp::Ordering::*;
763 ///
764 /// let mut x = Float::from_unsigned_prec(10u32, 100).0;
765 /// assert_eq!(x.log_base_2_prec_round_assign(5, Floor), Less);
766 /// assert_eq!(x.to_string(), "3.2");
767 ///
768 /// let mut x = Float::from_unsigned_prec(10u32, 100).0;
769 /// assert_eq!(x.log_base_2_prec_round_assign(5, Ceiling), Greater);
770 /// assert_eq!(x.to_string(), "3.4");
771 ///
772 /// let mut x = Float::from_unsigned_prec(10u32, 100).0;
773 /// assert_eq!(x.log_base_2_prec_round_assign(5, Nearest), Greater);
774 /// assert_eq!(x.to_string(), "3.4");
775 ///
776 /// let mut x = Float::from_unsigned_prec(10u32, 100).0;
777 /// assert_eq!(x.log_base_2_prec_round_assign(20, Floor), Less);
778 /// assert_eq!(x.to_string(), "3.321926");
779 ///
780 /// let mut x = Float::from_unsigned_prec(10u32, 100).0;
781 /// assert_eq!(x.log_base_2_prec_round_assign(20, Ceiling), Greater);
782 /// assert_eq!(x.to_string(), "3.32193");
783 ///
784 /// let mut x = Float::from_unsigned_prec(10u32, 100).0;
785 /// assert_eq!(x.log_base_2_prec_round_assign(20, Nearest), Greater);
786 /// assert_eq!(x.to_string(), "3.32193");
787 /// ```
788 #[inline]
789 pub fn log_base_2_prec_round_assign(&mut self, prec: u64, rm: RoundingMode) -> Ordering {
790 let (result, o) = core::mem::take(self).log_base_2_prec_round(prec, rm);
791 *self = result;
792 o
793 }
794
795 /// Computes $\log_2 x$, where $x$ is a [`Float`], in place, rounding the result to the nearest
796 /// value of the specified precision. An [`Ordering`] is returned, indicating whether the
797 /// rounded value is less than, equal to, or greater than the exact value. Although `NaN`s are
798 /// not comparable to any [`Float`], whenever this function sets the [`Float`] to `NaN` it also
799 /// returns `Equal`.
800 ///
801 /// The base-2 logarithm of any nonzero negative number is `NaN`.
802 ///
803 /// If the logarithm is equidistant from two [`Float`]s with the specified precision, the
804 /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
805 /// description of the `Nearest` rounding mode.
806 ///
807 /// $$
808 /// x \gets \log_2 x+\varepsilon.
809 /// $$
810 /// - If $\log_2 x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be
811 /// 0.
812 /// - If $\log_2 x$ is finite and nonzero, then $|\varepsilon| \leq 2^{\lfloor\log_2 |\log_2
813 /// x|\rfloor-p}$.
814 ///
815 /// If the output has a precision, it is `prec`.
816 ///
817 /// See the [`Float::log_base_2_prec`] documentation for information on special cases, overflow,
818 /// and underflow.
819 ///
820 /// If you want to use a rounding mode other than `Nearest`, consider using
821 /// [`Float::log_base_2_prec_round_assign`] instead. If you know that your target precision is
822 /// the precision of the input, consider using [`Float::log_base_2_assign`] instead.
823 ///
824 /// # Worst-case complexity
825 /// $T(n) = O(n (\log n)^2 \log\log n)$
826 ///
827 /// $M(n) = O(n (\log n)^2)$
828 ///
829 /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
830 ///
831 /// # Panics
832 /// Panics if `prec` is zero.
833 ///
834 /// # Examples
835 /// ```
836 /// use malachite_float::Float;
837 /// use std::cmp::Ordering::*;
838 ///
839 /// let mut x = Float::from_unsigned_prec(10u32, 100).0;
840 /// assert_eq!(x.log_base_2_prec_assign(5), Greater);
841 /// assert_eq!(x.to_string(), "3.4");
842 ///
843 /// let mut x = Float::from_unsigned_prec(10u32, 100).0;
844 /// assert_eq!(x.log_base_2_prec_assign(20), Greater);
845 /// assert_eq!(x.to_string(), "3.32193");
846 /// ```
847 #[inline]
848 pub fn log_base_2_prec_assign(&mut self, prec: u64) -> Ordering {
849 self.log_base_2_prec_round_assign(prec, Nearest)
850 }
851
852 /// Computes $\log_2 x$, where $x$ is a [`Float`], in place, rounding the result with the
853 /// specified rounding mode. An [`Ordering`] is returned, indicating whether the rounded value
854 /// is less than, equal to, or greater than the exact value. Although `NaN`s are not comparable
855 /// to any [`Float`], whenever this function sets the [`Float`] to `NaN` it also returns
856 /// `Equal`.
857 ///
858 /// The base-2 logarithm of any nonzero negative number is `NaN`.
859 ///
860 /// The precision of the output is the precision of the input. See [`RoundingMode`] for a
861 /// description of the possible rounding modes.
862 ///
863 /// $$
864 /// x \gets \log_2 x+\varepsilon.
865 /// $$
866 /// - If $\log_2 x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be
867 /// 0.
868 /// - If $\log_2 x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
869 /// 2^{\lfloor\log_2 |\log_2 x|\rfloor-p+1}$, where $p$ is the precision of the input.
870 /// - If $\log_2 x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
871 /// 2^{\lfloor\log_2 |\log_2 x|\rfloor-p}$, where $p$ is the precision of the input.
872 ///
873 /// If the output has a precision, it is the precision of the input.
874 ///
875 /// See the [`Float::log_base_2_round`] documentation for information on special cases,
876 /// overflow, and underflow.
877 ///
878 /// If you want to specify an output precision, consider using
879 /// [`Float::log_base_2_prec_round_assign`] instead. If you know you'll be using the `Nearest`
880 /// rounding mode, consider using [`Float::log_base_2_assign`] instead.
881 ///
882 /// # Worst-case complexity
883 /// $T(n) = O(n (\log n)^2 \log\log n)$
884 ///
885 /// $M(n) = O(n (\log n)^2)$
886 ///
887 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`.
888 ///
889 /// # Panics
890 /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input
891 /// precision. (The result is exactly representable if and only if the input is `NaN`, infinite,
892 /// zero, equal to 1, or a power of 2 whose base-2 logarithm is representable with the input
893 /// precision.)
894 ///
895 /// # Examples
896 /// ```
897 /// use malachite_base::rounding_modes::RoundingMode::*;
898 /// use malachite_float::Float;
899 /// use std::cmp::Ordering::*;
900 ///
901 /// let mut x = Float::from_unsigned_prec(10u32, 100).0;
902 /// assert_eq!(x.log_base_2_round_assign(Floor), Less);
903 /// assert_eq!(x.to_string(), "3.321928094887362347870319429487");
904 ///
905 /// let mut x = Float::from_unsigned_prec(10u32, 100).0;
906 /// assert_eq!(x.log_base_2_round_assign(Ceiling), Greater);
907 /// assert_eq!(x.to_string(), "3.32192809488736234787031942949");
908 ///
909 /// let mut x = Float::from_unsigned_prec(10u32, 100).0;
910 /// assert_eq!(x.log_base_2_round_assign(Nearest), Greater);
911 /// assert_eq!(x.to_string(), "3.32192809488736234787031942949");
912 /// ```
913 #[inline]
914 pub fn log_base_2_round_assign(&mut self, rm: RoundingMode) -> Ordering {
915 let prec = self.significant_bits();
916 self.log_base_2_prec_round_assign(prec, rm)
917 }
918
919 /// Computes $\log_2 x$, where $x$ is a [`Rational`], rounding the result to the specified
920 /// precision and with the specified rounding mode and returning the result as a [`Float`]. The
921 /// [`Rational`] is taken by value. An [`Ordering`] is also returned, indicating whether the
922 /// rounded value is less than, equal to, or greater than the exact value. Although `NaN`s are
923 /// not comparable to any [`Float`], whenever this function returns a `NaN` it also returns
924 /// `Equal`.
925 ///
926 /// The base-2 logarithm of any negative number is `NaN`.
927 ///
928 /// Inputs of any magnitude are handled, including [`Rational`]s whose magnitudes are too large
929 /// or too small to be representable as [`Float`]s.
930 ///
931 /// See [`RoundingMode`] for a description of the possible rounding modes.
932 ///
933 /// $$
934 /// f(x,p,m) = \log_2 x+\varepsilon.
935 /// $$
936 /// - If $\log_2 x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be
937 /// 0.
938 /// - If $\log_2 x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
939 /// 2^{\lfloor\log_2 |\log_2 x|\rfloor-p+1}$.
940 /// - If $\log_2 x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
941 /// 2^{\lfloor\log_2 |\log_2 x|\rfloor-p}$.
942 ///
943 /// If the output has a precision, it is `prec`.
944 ///
945 /// Special cases:
946 /// - $f(0,p,m)=-\infty$
947 /// - $f(x,p,m)=\text{NaN}$ for $x<0$
948 /// - $f(1,p,m)=0.0$, and the result is exact
949 /// - $f(2^k,p,m)=k$, rounded to precision $p$; the result is exact if and only if $k$ is
950 /// representable with precision $p$. This includes negative powers of 2 like $1/4$, and
951 /// powers of 2 whose exponents $k$ lie far outside the exponent range of [`Float`]; the
952 /// result is just the integer $k$ as a [`Float`].
953 ///
954 /// If you know you'll be using `Nearest`, consider using [`Float::log_base_2_rational_prec`]
955 /// instead.
956 ///
957 /// # Worst-case complexity
958 /// $T(n) = O(n (\log n)^2 \log\log n)$
959 ///
960 /// $M(n) = O(n (\log n)^2)$
961 ///
962 /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
963 ///
964 /// # Panics
965 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
966 /// with the given precision. (The result is exactly representable if and only if $x\leq 0$ or
967 /// $x$ is a power of 2 whose base-2 logarithm is representable with the given precision.)
968 ///
969 /// # Examples
970 /// ```
971 /// use malachite_base::rounding_modes::RoundingMode::*;
972 /// use malachite_float::Float;
973 /// use malachite_q::Rational;
974 /// use std::cmp::Ordering::*;
975 ///
976 /// let (log, o) =
977 /// Float::log_base_2_rational_prec_round(Rational::from_unsigneds(3u8, 5), 5, Floor);
978 /// assert_eq!(log.to_string(), "-0.75");
979 /// assert_eq!(o, Less);
980 ///
981 /// let (log, o) =
982 /// Float::log_base_2_rational_prec_round(Rational::from_unsigneds(3u8, 5), 5, Ceiling);
983 /// assert_eq!(log.to_string(), "-0.72");
984 /// assert_eq!(o, Greater);
985 ///
986 /// let (log, o) =
987 /// Float::log_base_2_rational_prec_round(Rational::from_unsigneds(3u8, 5), 5, Nearest);
988 /// assert_eq!(log.to_string(), "-0.75");
989 /// assert_eq!(o, Less);
990 ///
991 /// let (log, o) =
992 /// Float::log_base_2_rational_prec_round(Rational::from_unsigneds(3u8, 5), 20, Floor);
993 /// assert_eq!(log.to_string(), "-0.736966");
994 /// assert_eq!(o, Less);
995 ///
996 /// let (log, o) =
997 /// Float::log_base_2_rational_prec_round(Rational::from_unsigneds(3u8, 5), 20, Ceiling);
998 /// assert_eq!(log.to_string(), "-0.736965");
999 /// assert_eq!(o, Greater);
1000 ///
1001 /// let (log, o) =
1002 /// Float::log_base_2_rational_prec_round(Rational::from_unsigneds(3u8, 5), 20, Nearest);
1003 /// assert_eq!(log.to_string(), "-0.736965");
1004 /// assert_eq!(o, Greater);
1005 /// ```
1006 #[allow(clippy::needless_pass_by_value)]
1007 #[inline]
1008 pub fn log_base_2_rational_prec_round(
1009 x: Rational,
1010 prec: u64,
1011 rm: RoundingMode,
1012 ) -> (Self, Ordering) {
1013 Self::log_base_2_rational_prec_round_ref(&x, prec, rm)
1014 }
1015
1016 /// Computes $\log_2 x$, where $x$ is a [`Rational`], rounding the result to the specified
1017 /// precision and with the specified rounding mode and returning the result as a [`Float`]. The
1018 /// [`Rational`] is taken by reference. An [`Ordering`] is also returned, indicating whether the
1019 /// rounded value is less than, equal to, or greater than the exact value. Although `NaN`s are
1020 /// not comparable to any [`Float`], whenever this function returns a `NaN` it also returns
1021 /// `Equal`.
1022 ///
1023 /// The base-2 logarithm of any negative number is `NaN`.
1024 ///
1025 /// Inputs of any magnitude are handled, including [`Rational`]s whose magnitudes are too large
1026 /// or too small to be representable as [`Float`]s.
1027 ///
1028 /// See [`RoundingMode`] for a description of the possible rounding modes.
1029 ///
1030 /// $$
1031 /// f(x,p,m) = \log_2 x+\varepsilon.
1032 /// $$
1033 /// - If $\log_2 x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be
1034 /// 0.
1035 /// - If $\log_2 x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
1036 /// 2^{\lfloor\log_2 |\log_2 x|\rfloor-p+1}$.
1037 /// - If $\log_2 x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
1038 /// 2^{\lfloor\log_2 |\log_2 x|\rfloor-p}$.
1039 ///
1040 /// If the output has a precision, it is `prec`.
1041 ///
1042 /// Special cases:
1043 /// - $f(0,p,m)=-\infty$
1044 /// - $f(x,p,m)=\text{NaN}$ for $x<0$
1045 /// - $f(1,p,m)=0.0$, and the result is exact
1046 /// - $f(2^k,p,m)=k$, rounded to precision $p$; the result is exact if and only if $k$ is
1047 /// representable with precision $p$. This includes negative powers of 2 like $1/4$, and
1048 /// powers of 2 whose exponents $k$ lie far outside the exponent range of [`Float`]; the
1049 /// result is just the integer $k$ as a [`Float`].
1050 ///
1051 /// If you know you'll be using `Nearest`, consider using
1052 /// [`Float::log_base_2_rational_prec_ref`] instead.
1053 ///
1054 /// # Worst-case complexity
1055 /// $T(n) = O(n (\log n)^2 \log\log n)$
1056 ///
1057 /// $M(n) = O(n (\log n)^2)$
1058 ///
1059 /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
1060 ///
1061 /// # Panics
1062 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
1063 /// with the given precision. (The result is exactly representable if and only if $x\leq 0$ or
1064 /// $x$ is a power of 2 whose base-2 logarithm is representable with the given precision.)
1065 ///
1066 /// # Examples
1067 /// ```
1068 /// use malachite_base::rounding_modes::RoundingMode::*;
1069 /// use malachite_float::Float;
1070 /// use malachite_q::Rational;
1071 /// use std::cmp::Ordering::*;
1072 ///
1073 /// let (log, o) =
1074 /// Float::log_base_2_rational_prec_round_ref(&Rational::from_unsigneds(3u8, 5), 5, Floor);
1075 /// assert_eq!(log.to_string(), "-0.75");
1076 /// assert_eq!(o, Less);
1077 ///
1078 /// let (log, o) = Float::log_base_2_rational_prec_round_ref(
1079 /// &Rational::from_unsigneds(3u8, 5),
1080 /// 5,
1081 /// Ceiling,
1082 /// );
1083 /// assert_eq!(log.to_string(), "-0.72");
1084 /// assert_eq!(o, Greater);
1085 ///
1086 /// let (log, o) = Float::log_base_2_rational_prec_round_ref(
1087 /// &Rational::from_unsigneds(3u8, 5),
1088 /// 5,
1089 /// Nearest,
1090 /// );
1091 /// assert_eq!(log.to_string(), "-0.75");
1092 /// assert_eq!(o, Less);
1093 ///
1094 /// let (log, o) =
1095 /// Float::log_base_2_rational_prec_round_ref(&Rational::from_unsigneds(3u8, 5), 20, Floor);
1096 /// assert_eq!(log.to_string(), "-0.736966");
1097 /// assert_eq!(o, Less);
1098 ///
1099 /// let (log, o) = Float::log_base_2_rational_prec_round_ref(
1100 /// &Rational::from_unsigneds(3u8, 5),
1101 /// 20,
1102 /// Ceiling,
1103 /// );
1104 /// assert_eq!(log.to_string(), "-0.736965");
1105 /// assert_eq!(o, Greater);
1106 ///
1107 /// let (log, o) = Float::log_base_2_rational_prec_round_ref(
1108 /// &Rational::from_unsigneds(3u8, 5),
1109 /// 20,
1110 /// Nearest,
1111 /// );
1112 /// assert_eq!(log.to_string(), "-0.736965");
1113 /// assert_eq!(o, Greater);
1114 /// ```
1115 pub fn log_base_2_rational_prec_round_ref(
1116 x: &Rational,
1117 prec: u64,
1118 rm: RoundingMode,
1119 ) -> (Self, Ordering) {
1120 assert_ne!(prec, 0);
1121 match x.sign() {
1122 Equal => return (float_negative_infinity!(), Equal),
1123 Less => return (float_nan!(), Equal),
1124 Greater => {}
1125 }
1126 // If x is 2^k, log_base_2(x) is exact (though possibly subject to rounding at the target
1127 // precision).
1128 if let Some(k) = x.checked_log_base_2() {
1129 return Self::from_signed_prec_round(k, prec, rm);
1130 }
1131 // The result is never exactly representable for other inputs.
1132 assert_ne!(rm, Exact, "Inexact log_base_2");
1133 log_base_2_rational_prec_round_helper(x, prec, rm)
1134 }
1135
1136 /// Computes $\log_2 x$, where $x$ is a [`Rational`], rounding the result to the nearest value
1137 /// of the specified precision and returning the result as a [`Float`]. The [`Rational`] is
1138 /// taken by value. An [`Ordering`] is also returned, indicating whether the rounded value is
1139 /// less than, equal to, or greater than the exact value. Although `NaN`s are not comparable to
1140 /// any [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
1141 ///
1142 /// The base-2 logarithm of any negative number is `NaN`.
1143 ///
1144 /// Inputs of any magnitude are handled, including [`Rational`]s whose magnitudes are too large
1145 /// or too small to be representable as [`Float`]s.
1146 ///
1147 /// If the logarithm is equidistant from two [`Float`]s with the specified precision, the
1148 /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
1149 /// description of the `Nearest` rounding mode.
1150 ///
1151 /// $$
1152 /// f(x,p) = \log_2 x+\varepsilon.
1153 /// $$
1154 /// - If $\log_2 x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be
1155 /// 0.
1156 /// - If $\log_2 x$ is finite and nonzero, then $|\varepsilon| \leq 2^{\lfloor\log_2 |\log_2
1157 /// x|\rfloor-p}$.
1158 ///
1159 /// If the output has a precision, it is `prec`.
1160 ///
1161 /// Special cases:
1162 /// - $f(0,p)=-\infty$
1163 /// - $f(x,p)=\text{NaN}$ for $x<0$
1164 /// - $f(1,p)=0.0$, and the result is exact
1165 /// - $f(2^k,p)=k$, rounded to precision $p$; the result is exact if and only if $k$ is
1166 /// representable with precision $p$. This includes negative powers of 2 like $1/4$, and
1167 /// powers of 2 whose exponents $k$ lie far outside the exponent range of [`Float`]; the
1168 /// result is just the integer $k$ as a [`Float`].
1169 ///
1170 /// If you want to use a rounding mode other than `Nearest`, consider using
1171 /// [`Float::log_base_2_rational_prec_round`] instead.
1172 ///
1173 /// # Worst-case complexity
1174 /// $T(n) = O(n (\log n)^2 \log\log n)$
1175 ///
1176 /// $M(n) = O(n (\log n)^2)$
1177 ///
1178 /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
1179 ///
1180 /// # Panics
1181 /// Panics if `prec` is zero.
1182 ///
1183 /// # Examples
1184 /// ```
1185 /// use malachite_float::Float;
1186 /// use malachite_q::Rational;
1187 /// use std::cmp::Ordering::*;
1188 ///
1189 /// let (log, o) = Float::log_base_2_rational_prec(Rational::from_unsigneds(3u8, 5), 5);
1190 /// assert_eq!(log.to_string(), "-0.75");
1191 /// assert_eq!(o, Less);
1192 ///
1193 /// let (log, o) = Float::log_base_2_rational_prec(Rational::from_unsigneds(3u8, 5), 20);
1194 /// assert_eq!(log.to_string(), "-0.736965");
1195 /// assert_eq!(o, Greater);
1196 /// ```
1197 #[inline]
1198 pub fn log_base_2_rational_prec(x: Rational, prec: u64) -> (Self, Ordering) {
1199 Self::log_base_2_rational_prec_round(x, prec, Nearest)
1200 }
1201
1202 /// Computes $\log_2 x$, where $x$ is a [`Rational`], rounding the result to the nearest value
1203 /// of the specified precision and returning the result as a [`Float`]. The [`Rational`] is
1204 /// taken by reference. An [`Ordering`] is also returned, indicating whether the rounded value
1205 /// is less than, equal to, or greater than the exact value. Although `NaN`s are not comparable
1206 /// to any [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
1207 ///
1208 /// The base-2 logarithm of any negative number is `NaN`.
1209 ///
1210 /// Inputs of any magnitude are handled, including [`Rational`]s whose magnitudes are too large
1211 /// or too small to be representable as [`Float`]s.
1212 ///
1213 /// If the logarithm is equidistant from two [`Float`]s with the specified precision, the
1214 /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
1215 /// description of the `Nearest` rounding mode.
1216 ///
1217 /// $$
1218 /// f(x,p) = \log_2 x+\varepsilon.
1219 /// $$
1220 /// - If $\log_2 x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be
1221 /// 0.
1222 /// - If $\log_2 x$ is finite and nonzero, then $|\varepsilon| \leq 2^{\lfloor\log_2 |\log_2
1223 /// x|\rfloor-p}$.
1224 ///
1225 /// If the output has a precision, it is `prec`.
1226 ///
1227 /// Special cases:
1228 /// - $f(0,p)=-\infty$
1229 /// - $f(x,p)=\text{NaN}$ for $x<0$
1230 /// - $f(1,p)=0.0$, and the result is exact
1231 /// - $f(2^k,p)=k$, rounded to precision $p$; the result is exact if and only if $k$ is
1232 /// representable with precision $p$. This includes negative powers of 2 like $1/4$, and
1233 /// powers of 2 whose exponents $k$ lie far outside the exponent range of [`Float`]; the
1234 /// result is just the integer $k$ as a [`Float`].
1235 ///
1236 /// If you want to use a rounding mode other than `Nearest`, consider using
1237 /// [`Float::log_base_2_rational_prec_round_ref`] instead.
1238 ///
1239 /// # Worst-case complexity
1240 /// $T(n) = O(n (\log n)^2 \log\log n)$
1241 ///
1242 /// $M(n) = O(n (\log n)^2)$
1243 ///
1244 /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
1245 ///
1246 /// # Panics
1247 /// Panics if `prec` is zero.
1248 ///
1249 /// # Examples
1250 /// ```
1251 /// use malachite_float::Float;
1252 /// use malachite_q::Rational;
1253 /// use std::cmp::Ordering::*;
1254 ///
1255 /// let (log, o) = Float::log_base_2_rational_prec_ref(&Rational::from_unsigneds(3u8, 5), 5);
1256 /// assert_eq!(log.to_string(), "-0.75");
1257 /// assert_eq!(o, Less);
1258 ///
1259 /// let (log, o) = Float::log_base_2_rational_prec_ref(&Rational::from_unsigneds(3u8, 5), 20);
1260 /// assert_eq!(log.to_string(), "-0.736965");
1261 /// assert_eq!(o, Greater);
1262 /// ```
1263 #[inline]
1264 pub fn log_base_2_rational_prec_ref(x: &Rational, prec: u64) -> (Self, Ordering) {
1265 Self::log_base_2_rational_prec_round_ref(x, prec, Nearest)
1266 }
1267}
1268
1269impl LogBase2 for Float {
1270 type Output = Self;
1271
1272 /// Computes $\log_2 x$, where $x$ is a [`Float`], taking it by value.
1273 ///
1274 /// If the output has a precision, it is the precision of the input. If the logarithm is
1275 /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in
1276 /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
1277 /// rounding mode.
1278 ///
1279 /// The base-2 logarithm of any nonzero negative number is `NaN`.
1280 ///
1281 /// $$
1282 /// f(x) = \log_2 x+\varepsilon.
1283 /// $$
1284 /// - If $\log_2 x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be
1285 /// 0.
1286 /// - If $\log_2 x$ is finite and nonzero, then $|\varepsilon| \leq 2^{\lfloor\log_2 |\log_2
1287 /// x|\rfloor-p}$, where $p$ is the precision of the input.
1288 ///
1289 /// Special cases:
1290 /// - $f(\text{NaN})=\text{NaN}$
1291 /// - $f(\infty)=\infty$
1292 /// - $f(-\infty)=\text{NaN}$
1293 /// - $f(\pm0.0)=-\infty$
1294 /// - $f(1.0)=0.0$, and the result is exact
1295 /// - $f(2^k)=k$, rounded to the precision of the input; the result is exact if and only if $k$
1296 /// is representable with that precision
1297 /// - $f(x)=\text{NaN}$ for $x<0$
1298 ///
1299 /// Neither overflow nor underflow is possible.
1300 ///
1301 /// If you want to use a rounding mode other than `Nearest`, consider using
1302 /// [`Float::log_base_2_round`] instead. If you want to specify the output precision, consider
1303 /// using [`Float::log_base_2_prec`]. If you want both of these things, consider using
1304 /// [`Float::log_base_2_prec_round`].
1305 ///
1306 /// # Worst-case complexity
1307 /// $T(n) = O(n (\log n)^2 \log\log n)$
1308 ///
1309 /// $M(n) = O(n (\log n)^2)$
1310 ///
1311 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`.
1312 ///
1313 /// # Examples
1314 /// ```
1315 /// use malachite_base::num::arithmetic::traits::LogBase2;
1316 /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity};
1317 /// use malachite_float::Float;
1318 ///
1319 /// assert!(Float::NAN.log_base_2().is_nan());
1320 /// assert_eq!(Float::INFINITY.log_base_2(), Float::INFINITY);
1321 /// assert!(Float::NEGATIVE_INFINITY.log_base_2().is_nan());
1322 /// assert_eq!(
1323 /// Float::from_unsigned_prec(10u32, 100)
1324 /// .0
1325 /// .log_base_2()
1326 /// .to_string(),
1327 /// "3.32192809488736234787031942949"
1328 /// );
1329 /// assert!(Float::from_signed_prec(-10, 100).0.log_base_2().is_nan());
1330 /// ```
1331 #[inline]
1332 fn log_base_2(self) -> Self {
1333 let prec = self.significant_bits();
1334 self.log_base_2_prec_round(prec, Nearest).0
1335 }
1336}
1337
1338impl LogBase2 for &Float {
1339 type Output = Float;
1340
1341 /// Computes $\log_2 x$, where $x$ is a [`Float`], taking it by reference.
1342 ///
1343 /// If the output has a precision, it is the precision of the input. If the logarithm is
1344 /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in
1345 /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
1346 /// rounding mode.
1347 ///
1348 /// The base-2 logarithm of any nonzero negative number is `NaN`.
1349 ///
1350 /// $$
1351 /// f(x) = \log_2 x+\varepsilon.
1352 /// $$
1353 /// - If $\log_2 x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be
1354 /// 0.
1355 /// - If $\log_2 x$ is finite and nonzero, then $|\varepsilon| \leq 2^{\lfloor\log_2 |\log_2
1356 /// x|\rfloor-p}$, where $p$ is the precision of the input.
1357 ///
1358 /// Special cases:
1359 /// - $f(\text{NaN})=\text{NaN}$
1360 /// - $f(\infty)=\infty$
1361 /// - $f(-\infty)=\text{NaN}$
1362 /// - $f(\pm0.0)=-\infty$
1363 /// - $f(1.0)=0.0$, and the result is exact
1364 /// - $f(2^k)=k$, rounded to the precision of the input; the result is exact if and only if $k$
1365 /// is representable with that precision
1366 /// - $f(x)=\text{NaN}$ for $x<0$
1367 ///
1368 /// Neither overflow nor underflow is possible.
1369 ///
1370 /// If you want to use a rounding mode other than `Nearest`, consider using
1371 /// [`Float::log_base_2_round_ref`] instead. If you want to specify the output precision,
1372 /// consider using [`Float::log_base_2_prec_ref`]. If you want both of these things, consider
1373 /// using [`Float::log_base_2_prec_round_ref`].
1374 ///
1375 /// # Worst-case complexity
1376 /// $T(n) = O(n (\log n)^2 \log\log n)$
1377 ///
1378 /// $M(n) = O(n (\log n)^2)$
1379 ///
1380 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`.
1381 ///
1382 /// # Examples
1383 /// ```
1384 /// use malachite_base::num::arithmetic::traits::LogBase2;
1385 /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity};
1386 /// use malachite_float::Float;
1387 ///
1388 /// assert!((&Float::NAN).log_base_2().is_nan());
1389 /// assert_eq!((&Float::INFINITY).log_base_2(), Float::INFINITY);
1390 /// assert!((&Float::NEGATIVE_INFINITY).log_base_2().is_nan());
1391 /// assert_eq!(
1392 /// (&Float::from_unsigned_prec(10u32, 100).0)
1393 /// .log_base_2()
1394 /// .to_string(),
1395 /// "3.32192809488736234787031942949"
1396 /// );
1397 /// assert!((&Float::from_signed_prec(-10, 100).0).log_base_2().is_nan());
1398 /// ```
1399 #[inline]
1400 fn log_base_2(self) -> Float {
1401 let prec = self.significant_bits();
1402 self.log_base_2_prec_round_ref(prec, Nearest).0
1403 }
1404}
1405
1406impl LogBase2Assign for Float {
1407 /// Computes $\log_2 x$, where $x$ is a [`Float`], in place.
1408 ///
1409 /// If the output has a precision, it is the precision of the input. If the logarithm is
1410 /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in
1411 /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
1412 /// rounding mode.
1413 ///
1414 /// The base-2 logarithm of any nonzero negative number is `NaN`.
1415 ///
1416 /// $$
1417 /// x \gets \log_2 x+\varepsilon.
1418 /// $$
1419 /// - If $\log_2 x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be
1420 /// 0.
1421 /// - If $\log_2 x$ is finite and nonzero, then $|\varepsilon| \leq 2^{\lfloor\log_2 |\log_2
1422 /// x|\rfloor-p}$, where $p$ is the precision of the input.
1423 ///
1424 /// See the [`Float::log_base_2`] documentation for information on special cases, overflow, and
1425 /// underflow.
1426 ///
1427 /// If you want to use a rounding mode other than `Nearest`, consider using
1428 /// [`Float::log_base_2_round_assign`] instead. If you want to specify the output precision,
1429 /// consider using [`Float::log_base_2_prec_assign`]. If you want both of these things, consider
1430 /// using [`Float::log_base_2_prec_round_assign`].
1431 ///
1432 /// # Worst-case complexity
1433 /// $T(n) = O(n (\log n)^2 \log\log n)$
1434 ///
1435 /// $M(n) = O(n (\log n)^2)$
1436 ///
1437 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`.
1438 ///
1439 /// # Examples
1440 /// ```
1441 /// use malachite_base::num::arithmetic::traits::LogBase2Assign;
1442 /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity};
1443 /// use malachite_float::Float;
1444 ///
1445 /// let mut x = Float::NAN;
1446 /// x.log_base_2_assign();
1447 /// assert!(x.is_nan());
1448 ///
1449 /// let mut x = Float::INFINITY;
1450 /// x.log_base_2_assign();
1451 /// assert_eq!(x, Float::INFINITY);
1452 ///
1453 /// let mut x = Float::NEGATIVE_INFINITY;
1454 /// x.log_base_2_assign();
1455 /// assert!(x.is_nan());
1456 ///
1457 /// let mut x = Float::from_unsigned_prec(10u32, 100).0;
1458 /// x.log_base_2_assign();
1459 /// assert_eq!(x.to_string(), "3.32192809488736234787031942949");
1460 ///
1461 /// let mut x = Float::from_signed_prec(-10, 100).0;
1462 /// x.log_base_2_assign();
1463 /// assert!(x.is_nan());
1464 /// ```
1465 #[inline]
1466 fn log_base_2_assign(&mut self) {
1467 let prec = self.significant_bits();
1468 self.log_base_2_prec_round_assign(prec, Nearest);
1469 }
1470}
1471
1472/// Computes the base-2 logarithm of a primitive float, $\log_2 x$.
1473///
1474/// This function is correctly rounded. The standard library's `log2` is correctly rounded for
1475/// [`f32`] but not always for [`f64`], so for some [`f64`] inputs this function is more accurate.
1476///
1477/// The base-2 logarithm of any nonzero negative number is `NaN`.
1478///
1479/// $$
1480/// f(x) = \log_2 x+\varepsilon.
1481/// $$
1482/// - If $\log_2 x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
1483/// - If $\log_2 x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |\log_2
1484/// x|\rfloor-p}$, where $p$ is precision of the output (typically 24 if `T` is a [`f32`] and 53
1485/// if `T` is a [`f64`], but less if the output is subnormal).
1486///
1487/// Special cases:
1488/// - $f(\text{NaN})=\text{NaN}$
1489/// - $f(\infty)=\infty$
1490/// - $f(-\infty)=\text{NaN}$
1491/// - $f(\pm0.0)=-\infty$
1492/// - $f(x)=\text{NaN}$ for $x<0$
1493///
1494/// Neither overflow nor underflow is possible.
1495///
1496/// # Worst-case complexity
1497/// Constant time and additional memory.
1498///
1499/// # Examples
1500/// ```
1501/// use malachite_base::num::basic::traits::NegativeInfinity;
1502/// use malachite_base::num::float::NiceFloat;
1503/// use malachite_float::arithmetic::log_base_2::primitive_float_log_base_2;
1504///
1505/// assert!(primitive_float_log_base_2(f32::NAN).is_nan());
1506/// assert_eq!(
1507/// NiceFloat(primitive_float_log_base_2(f32::INFINITY)),
1508/// NiceFloat(f32::INFINITY)
1509/// );
1510/// assert!(primitive_float_log_base_2(f32::NEGATIVE_INFINITY).is_nan());
1511/// assert_eq!(
1512/// NiceFloat(primitive_float_log_base_2(0.0f32)),
1513/// NiceFloat(f32::NEGATIVE_INFINITY)
1514/// );
1515/// assert_eq!(
1516/// NiceFloat(primitive_float_log_base_2(8.0f32)),
1517/// NiceFloat(3.0)
1518/// );
1519/// assert_eq!(
1520/// NiceFloat(primitive_float_log_base_2(10.0f32)),
1521/// NiceFloat(3.321928)
1522/// );
1523/// assert!(primitive_float_log_base_2(-10.0f32).is_nan());
1524/// ```
1525#[inline]
1526#[allow(clippy::type_repetition_in_bounds)]
1527pub fn primitive_float_log_base_2<T: PrimitiveFloat>(x: T) -> T
1528where
1529 Float: From<T> + PartialOrd<T>,
1530 for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
1531{
1532 emulate_float_to_float_fn(Float::log_base_2_prec, x)
1533}
1534
1535/// Computes the base-2 logarithm of a [`Rational`], returning a primitive float result.
1536///
1537/// If the logarithm is equidistant from two primitive floats, the primitive float with fewer 1s in
1538/// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest` rounding
1539/// mode.
1540///
1541/// The logarithm of any negative number is `NaN`.
1542///
1543/// $$
1544/// f(x) = \log_2{x}+\varepsilon.
1545/// $$
1546/// - If $\log_2{x}$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
1547/// - If $\log_2{x}$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2
1548/// |\log_2{x}|\rfloor-p}$, where $p$ is precision of the output (typically 24 if `T` is a [`f32`]
1549/// and 53 if `T` is a [`f64`], but less if the output is subnormal).
1550///
1551/// Special cases:
1552/// - $f(0)=-\infty$
1553///
1554/// Neither overflow nor underflow is possible.
1555///
1556/// # Worst-case complexity
1557/// Constant time and additional memory.
1558///
1559/// # Examples
1560/// ```
1561/// use malachite_base::num::basic::traits::{NegativeInfinity, Zero};
1562/// use malachite_base::num::float::NiceFloat;
1563/// use malachite_float::arithmetic::log_base_2::primitive_float_log_base_2_rational;
1564/// use malachite_q::Rational;
1565///
1566/// assert_eq!(
1567/// NiceFloat(primitive_float_log_base_2_rational::<f64>(&Rational::ZERO)),
1568/// NiceFloat(f64::NEGATIVE_INFINITY)
1569/// );
1570/// assert_eq!(
1571/// NiceFloat(primitive_float_log_base_2_rational::<f64>(
1572/// &Rational::from_unsigneds(1u8, 3)
1573/// )),
1574/// NiceFloat(-1.584962500721156)
1575/// );
1576/// assert_eq!(
1577/// NiceFloat(primitive_float_log_base_2_rational::<f64>(&Rational::from(
1578/// 10000
1579/// ))),
1580/// NiceFloat(13.287712379549449)
1581/// );
1582/// assert_eq!(
1583/// NiceFloat(primitive_float_log_base_2_rational::<f64>(&Rational::from(
1584/// -10000
1585/// ))),
1586/// NiceFloat(f64::NAN)
1587/// );
1588/// ```
1589#[inline]
1590#[allow(clippy::type_repetition_in_bounds)]
1591pub fn primitive_float_log_base_2_rational<T: PrimitiveFloat>(x: &Rational) -> T
1592where
1593 Float: PartialOrd<T>,
1594 for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
1595{
1596 emulate_rational_to_float_fn(Float::log_base_2_rational_prec_ref, x)
1597}