malachite_float/arithmetic/log_base_power_of_2_1_plus_x.rs
1// Copyright © 2026 Mikhail Hogrefe
2//
3// This file is part of Malachite.
4//
5// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
6// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
7// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
8
9use crate::InnerFloat::{Infinity, NaN, Zero};
10use crate::arithmetic::log_base_2_1_plus_x::log_base_2_1_plus_x_exact;
11use crate::{Float, emulate_float_to_float_fn, float_infinity, float_nan, float_negative_infinity};
12use core::cmp::Ordering::{self, *};
13use malachite_base::num::arithmetic::traits::{
14 CeilingLogBase2, IsPowerOf2, LogBasePowerOf2Of1PlusX, LogBasePowerOf2Of1PlusXAssign,
15};
16use malachite_base::num::basic::floats::PrimitiveFloat;
17use malachite_base::num::basic::integers::PrimitiveInt;
18use malachite_base::num::comparison::traits::PartialOrdAbs;
19use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom};
20use malachite_base::num::logic::traits::SignificantBits;
21use malachite_base::rounding_modes::RoundingMode::{self, *};
22use malachite_nz::natural::arithmetic::float_extras::float_can_round;
23use malachite_nz::platform::Limb;
24
25// The computation of log_base_power_of_2_1_plus_x(x, pow) is done by log_{2^pow}(1 + x) = log_2(1 +
26// x) / pow, where the input is finite, nonzero, and greater than -1.
27fn log_base_power_of_2_1_plus_x_prec_round_normal(
28 x: &Float,
29 pow: i64,
30 prec: u64,
31 rm: RoundingMode,
32) -> (Float, Ordering) {
33 // log_{2^pow}(1 + x) is undefined for x < -1.
34 match x.partial_cmp(&-1i32).unwrap() {
35 // 1 + x = 0, so log_2(1 + x) = -infinity.
36 Equal => {
37 return (
38 if pow > 0 {
39 float_negative_infinity!()
40 } else {
41 float_infinity!()
42 },
43 Equal,
44 );
45 }
46 Less => return (float_nan!(), Equal),
47 _ => {}
48 }
49 // If 1 + x is exactly 2^m, then log_2(1 + x) = m and the result is the rational m / pow (exact
50 // when representable at the target precision).
51 if let Some(m) = log_base_2_1_plus_x_exact(x) {
52 return Float::from(m).div_prec_round(Float::from(pow), prec, rm);
53 }
54 // The result is never exactly representable otherwise.
55 assert_ne!(rm, Exact, "Inexact log_base_power_of_2_1_plus_x");
56 let pow_f = Float::from(pow);
57 let e_pow = i64::from(pow_f.get_exponent().unwrap());
58 let min_exp = i64::from(Float::MIN_EXPONENT);
59 // If x = 2^k for a k large enough that 1 + x is astronomically close to 2^k, then log_2(1 + x)
60 // is k plus a positive infinitesimal (delta < 2^(2 - expx)), so log_{2^pow}(1 + x) is k / pow
61 // nudged infinitesimally away from k / pow (toward +infinity when pow > 0, toward -infinity
62 // when pow < 0). The Ziv loop below could never resolve this: log_2(1 + x) rounds to exactly k
63 // at every working precision (this is log_base_2_1_plus_x's own `_special` regime), so when k /
64 // pow is exactly representable the rounding test can never certify it and the precision grows
65 // without bound. Handle it directly, but only once delta is below a quarter ulp of the *result*
66 // k / pow (note the deviation must be measured at the result's scale, e_res, not k's scale --
67 // dividing by pow can make the ulp finer relative to delta); otherwise delta is large enough
68 // that the ordinary Ziv loop both terminates and is needed for correctness.
69 if x.is_power_of_2() {
70 let expx = i64::from(x.get_exponent().unwrap());
71 let k = expx - 1; // x = 2^k
72 if k >= 1 {
73 // log_2(1 + x) lies in (k, k + delta). Represent "just above k" at a precision high
74 // enough that the nudge, once divided by pow, stays far below one ulp of k / pow (so it
75 // shares k / pow's rounding cell) yet is strictly nonzero. This pushes a representable
76 // or tied k / pow off the boundary in the correct direction, so div_prec_round returns
77 // the correctly-rounded value and ternary for the true (infinitesimally offset) result.
78 let high_prec = prec + e_pow.unsigned_abs() + Limb::WIDTH;
79 let mut t = Float::from_signed_prec(k, high_prec).0;
80 t.increment();
81 let (res, o) = t.div_prec_round(pow_f.clone(), prec, rm);
82 let e_res = i64::from(res.get_exponent().unwrap());
83 if 2 - expx < e_res - i64::exact_from(prec) - 1 {
84 return (res, o);
85 }
86 }
87 }
88 let mut working_prec = prec + 3 + prec.ceiling_log_base_2();
89 let mut increment = Limb::WIDTH;
90 loop {
91 // log_2(1 + x), correctly rounded to working_prec.
92 let num = x.log_base_2_1_plus_x_prec_ref(working_prec).0;
93 // log_2(1 + x) is always within the Float exponent range, but dividing by pow (with |pow| >
94 // 1) can push the result below MIN_EXPONENT; overflow is impossible, since |pow| >= 1 means
95 // |result| <= |log_2(1 + x)|. The quotient's exponent is e_num - e_pow or e_num - e_pow +
96 // 1. When the result underflows, the Ziv test below can never resolve it (the quotient
97 // clamps to a power of 2 at MIN_EXPONENT), so hand the rounding to div_prec_round, which
98 // clamps to zero or the minimum positive value per the rounding mode. The exact quotient
99 // exponent is resolved only in the narrow band where the cheap exponent bound is
100 // inconclusive (then e_num - e_pow == min_exp - 1, so the result underflows iff |log_2(1 +
101 // x) / pow| < 2^(min_exp - 1), i.e. iff |log_2(1 + x)| * 2^(1 - min_exp) < |pow|). The left
102 // shift only adjusts the exponent (the shifted value's exponent is e_pow, well within
103 // range), so this avoids converting a near-MIN_EXPONENT `num` to a `Rational` with a
104 // ~2^30-bit denominator.
105 let e_num = i64::from(num.get_exponent().unwrap());
106 if e_num - e_pow + 1 < min_exp
107 || (e_num - e_pow < min_exp && (&num << u64::exact_from(1 - min_exp)).lt_abs(&pow_f))
108 {
109 return num.div_prec_round(pow_f, prec, rm);
110 }
111 // log_2(1 + x) / pow, with two correctly-rounded operations: log_base_2_1_plus_x (at most
112 // 1/2 ulp) and division by the exact integer pow (at most 1/2 ulp). The relative error is
113 // thus below 2^(1 - working_prec), so working_prec - 2 correct bits suffice for rounding.
114 // (log_base_2_1_plus_x itself handles inputs x = 2^k with k so large that 1 + x is
115 // astronomically close to a power of 2, so no extra precision is needed here.)
116 let t = num.div_prec(pow_f.clone(), working_prec).0;
117 if float_can_round(t.significand_ref().unwrap(), working_prec - 2, prec, rm) {
118 return Float::from_float_prec_round(t, prec, rm);
119 }
120 // Increase the precision.
121 working_prec += increment;
122 increment = working_prec >> 1;
123 }
124}
125
126impl Float {
127 /// Computes $\log_{2^k}(1+x)$, where $x$ is a [`Float`] and the base is $2^k$ for some nonzero
128 /// integer $k$, rounding the result to the specified precision and with the specified rounding
129 /// mode. The base's exponent $k$ is `pow`, which may be negative. The [`Float`] is taken by
130 /// value. An [`Ordering`] is also returned, indicating whether the rounded value is less than,
131 /// equal to, or greater than the exact value. Although `NaN`s are not comparable to any
132 /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
133 ///
134 /// $\log_{2^k}(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, `NaN` is returned.
135 ///
136 /// See [`RoundingMode`] for a description of the possible rounding modes.
137 ///
138 /// $$
139 /// f(x,k,p,m) = \log_{2^k}(1+x)+\varepsilon.
140 /// $$
141 /// - If $\log_{2^k}(1+x)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
142 /// to be 0.
143 /// - If $\log_{2^k}(1+x)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon|
144 /// < 2^{\lfloor\log_2 |\log_{2^k}(1+x)|\rfloor-p+1}$.
145 /// - If $\log_{2^k}(1+x)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
146 /// 2^{\lfloor\log_2 |\log_{2^k}(1+x)|\rfloor-p}$.
147 ///
148 /// If the output has a precision, it is `prec`.
149 ///
150 /// Special cases:
151 /// - $f(\text{NaN},k,p,m)=\text{NaN}$
152 /// - $f(\infty,k,p,m)=\infty$ if $k>0$, and $-\infty$ if $k<0$
153 /// - $f(-\infty,k,p,m)=\text{NaN}$
154 /// - $f(0.0,k,p,m)=0.0$ if $k>0$, and $-0.0$ if $k<0$
155 /// - $f(-0.0,k,p,m)=-0.0$ if $k>0$, and $0.0$ if $k<0$
156 /// - $f(-1.0,k,p,m)=-\infty$ if $k>0$, and $\infty$ if $k<0$
157 /// - $f(x,k,p,m)=\text{NaN}$ for $x<-1$
158 /// - $f(x,k,p,m)=m/k$ when $1+x=2^m$, rounded to precision $p$; the result is exact if and only
159 /// if $m/k$ is representable with precision $p$ (for example $\log_4 8=3/2$ when $x=7$ is
160 /// exact, but $\log_8 4=2/3$ when $x=3$ is not)
161 ///
162 /// This function cannot overflow, but it can underflow:
163 /// - If $0<f(x,k,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
164 /// - If $0<f(x,k,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
165 /// instead.
166 /// - If $0<f(x,k,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
167 /// - If $2^{-2^{30}-1}<f(x,k,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
168 /// instead.
169 /// - If $-2^{-2^{30}}<f(x,k,p,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned
170 /// instead.
171 /// - If $-2^{-2^{30}}<f(x,k,p,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
172 /// instead.
173 /// - If $-2^{-2^{30}-1}\leq f(x,k,p,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
174 /// - If $-2^{-2^{30}}<f(x,k,p,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
175 /// returned instead.
176 ///
177 /// If you know you'll be using `Nearest`, consider using
178 /// [`Float::log_base_power_of_2_1_plus_x_prec`] instead. If you know that your target precision
179 /// is the precision of the input, consider using [`Float::log_base_power_of_2_1_plus_x_round`]
180 /// instead. If both of these things are true, consider using
181 /// [`Float::log_base_power_of_2_1_plus_x`] instead.
182 ///
183 /// # Worst-case complexity
184 /// $T(n) = O(n (\log n)^2 \log\log n)$
185 ///
186 /// $M(n) = O(n (\log n)^2)$
187 ///
188 /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
189 ///
190 /// # Panics
191 /// Panics if `prec` is zero, if `pow` is zero (the base $2^0=1$ has no logarithm), or if `rm`
192 /// is `Exact` but the result cannot be represented exactly with the given precision.
193 ///
194 /// # Examples
195 /// ```
196 /// use malachite_base::rounding_modes::RoundingMode::*;
197 /// use malachite_float::Float;
198 /// use std::cmp::Ordering::*;
199 ///
200 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
201 /// .0
202 /// .log_base_power_of_2_1_plus_x_prec_round(2, 20, Floor);
203 /// assert_eq!(log.to_string(), "1.729715");
204 /// assert_eq!(o, Less);
205 ///
206 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
207 /// .0
208 /// .log_base_power_of_2_1_plus_x_prec_round(2, 20, Ceiling);
209 /// assert_eq!(log.to_string(), "1.729717");
210 /// assert_eq!(o, Greater);
211 /// ```
212 #[inline]
213 pub fn log_base_power_of_2_1_plus_x_prec_round(
214 self,
215 pow: i64,
216 prec: u64,
217 rm: RoundingMode,
218 ) -> (Self, Ordering) {
219 assert_ne!(prec, 0);
220 assert_ne!(pow, 0, "Cannot take base-1 logarithm");
221 match self {
222 Self(NaN | Infinity { sign: false }) => (float_nan!(), Equal),
223 float_infinity!() => (
224 if pow > 0 {
225 float_infinity!()
226 } else {
227 float_negative_infinity!()
228 },
229 Equal,
230 ),
231 // log_{2^pow}(1 ± 0) = ±0, with the sign flipped when pow < 0
232 Self(Zero { .. }) => (if pow > 0 { self } else { -self }, Equal),
233 _ => log_base_power_of_2_1_plus_x_prec_round_normal(&self, pow, prec, rm),
234 }
235 }
236
237 /// Computes $\log_{2^k}(1+x)$, where $x$ is a [`Float`] and the base is $2^k$ for some nonzero
238 /// integer $k$, rounding the result to the specified precision and with the specified rounding
239 /// mode. The base's exponent $k$ is `pow`, which may be negative. The [`Float`] is taken by
240 /// reference. An [`Ordering`] is also returned, indicating whether the rounded value is less
241 /// than, equal to, or greater than the exact value. Although `NaN`s are not comparable to any
242 /// [`Float`], whenever this function returns a `NaN` it also returns `Equal`.
243 ///
244 /// $\log_{2^k}(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, `NaN` is returned.
245 ///
246 /// See [`RoundingMode`] for a description of the possible rounding modes.
247 ///
248 /// $$
249 /// f(x,k,p,m) = \log_{2^k}(1+x)+\varepsilon.
250 /// $$
251 /// - If $\log_{2^k}(1+x)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
252 /// to be 0.
253 /// - If $\log_{2^k}(1+x)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon|
254 /// < 2^{\lfloor\log_2 |\log_{2^k}(1+x)|\rfloor-p+1}$.
255 /// - If $\log_{2^k}(1+x)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
256 /// 2^{\lfloor\log_2 |\log_{2^k}(1+x)|\rfloor-p}$.
257 ///
258 /// If the output has a precision, it is `prec`.
259 ///
260 /// Special cases:
261 /// - $f(\text{NaN},k,p,m)=\text{NaN}$
262 /// - $f(\infty,k,p,m)=\infty$ if $k>0$, and $-\infty$ if $k<0$
263 /// - $f(-\infty,k,p,m)=\text{NaN}$
264 /// - $f(0.0,k,p,m)=0.0$ if $k>0$, and $-0.0$ if $k<0$
265 /// - $f(-0.0,k,p,m)=-0.0$ if $k>0$, and $0.0$ if $k<0$
266 /// - $f(-1.0,k,p,m)=-\infty$ if $k>0$, and $\infty$ if $k<0$
267 /// - $f(x,k,p,m)=\text{NaN}$ for $x<-1$
268 /// - $f(x,k,p,m)=m/k$ when $1+x=2^m$, rounded to precision $p$; the result is exact if and only
269 /// if $m/k$ is representable with precision $p$ (for example $\log_4 8=3/2$ when $x=7$ is
270 /// exact, but $\log_8 4=2/3$ when $x=3$ is not)
271 ///
272 /// This function cannot overflow, but it can underflow:
273 /// - If $0<f(x,k,p,m)<2^{-2^{30}}$, and $m$ is `Floor` or `Down`, $0.0$ is returned instead.
274 /// - If $0<f(x,k,p,m)<2^{-2^{30}}$, and $m$ is `Ceiling` or `Up`, $2^{-2^{30}}$ is returned
275 /// instead.
276 /// - If $0<f(x,k,p,m)\leq2^{-2^{30}-1}$, and $m$ is `Nearest`, $0.0$ is returned instead.
277 /// - If $2^{-2^{30}-1}<f(x,k,p,m)<2^{-2^{30}}$, and $m$ is `Nearest`, $2^{-2^{30}}$ is returned
278 /// instead.
279 /// - If $-2^{-2^{30}}<f(x,k,p,m)<0$, and $m$ is `Ceiling` or `Down`, $-0.0$ is returned
280 /// instead.
281 /// - If $-2^{-2^{30}}<f(x,k,p,m)<0$, and $m$ is `Floor` or `Up`, $-2^{-2^{30}}$ is returned
282 /// instead.
283 /// - If $-2^{-2^{30}-1}\leq f(x,k,p,m)<0$, and $m$ is `Nearest`, $-0.0$ is returned instead.
284 /// - If $-2^{-2^{30}}<f(x,k,p,m)<-2^{-2^{30}-1}$, and $m$ is `Nearest`, $-2^{-2^{30}}$ is
285 /// returned instead.
286 ///
287 /// If you know you'll be using `Nearest`, consider using
288 /// [`Float::log_base_power_of_2_1_plus_x_prec_ref`] instead. If you know that your target
289 /// precision is the precision of the input, consider using
290 /// [`Float::log_base_power_of_2_1_plus_x_round_ref`] instead. If both of these things are true,
291 /// consider using `(&Float).log_base_power_of_2_1_plus_x()` instead.
292 ///
293 /// # Worst-case complexity
294 /// $T(n) = O(n (\log n)^2 \log\log n)$
295 ///
296 /// $M(n) = O(n (\log n)^2)$
297 ///
298 /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
299 ///
300 /// # Panics
301 /// Panics if `prec` is zero, if `pow` is zero (the base $2^0=1$ has no logarithm), or if `rm`
302 /// is `Exact` but the result cannot be represented exactly with the given precision.
303 ///
304 /// # Examples
305 /// ```
306 /// use malachite_base::rounding_modes::RoundingMode::*;
307 /// use malachite_float::Float;
308 /// use std::cmp::Ordering::*;
309 ///
310 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
311 /// .0
312 /// .log_base_power_of_2_1_plus_x_prec_round_ref(2, 20, Floor);
313 /// assert_eq!(log.to_string(), "1.729715");
314 /// assert_eq!(o, Less);
315 ///
316 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
317 /// .0
318 /// .log_base_power_of_2_1_plus_x_prec_round_ref(2, 20, Ceiling);
319 /// assert_eq!(log.to_string(), "1.729717");
320 /// assert_eq!(o, Greater);
321 /// ```
322 #[inline]
323 pub fn log_base_power_of_2_1_plus_x_prec_round_ref(
324 &self,
325 pow: i64,
326 prec: u64,
327 rm: RoundingMode,
328 ) -> (Self, Ordering) {
329 assert_ne!(prec, 0);
330 assert_ne!(pow, 0, "Cannot take base-1 logarithm");
331 match self {
332 Self(NaN | Infinity { sign: false }) => (float_nan!(), Equal),
333 float_infinity!() => (
334 if pow > 0 {
335 float_infinity!()
336 } else {
337 float_negative_infinity!()
338 },
339 Equal,
340 ),
341 // log_{2^pow}(1 ± 0) = ±0, with the sign flipped when pow < 0
342 Self(Zero { .. }) => (if pow > 0 { self.clone() } else { -self }, Equal),
343 _ => log_base_power_of_2_1_plus_x_prec_round_normal(self, pow, prec, rm),
344 }
345 }
346
347 /// Computes $\log_{2^k}(1+x)$, where $x$ is a [`Float`] and the base is $2^k$ for some nonzero
348 /// integer $k$, rounding the result to the nearest value of the specified precision. The base's
349 /// exponent $k$ is `pow`, which may be negative. The [`Float`] is taken by value. An
350 /// [`Ordering`] is also returned, indicating whether the rounded value is less than, equal to,
351 /// or greater than the exact value. Although `NaN`s are not comparable to any [`Float`],
352 /// whenever this function returns a `NaN` it also returns `Equal`.
353 ///
354 /// $\log_{2^k}(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, `NaN` is returned.
355 ///
356 /// If the logarithm is equidistant from two [`Float`]s with the specified precision, the
357 /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
358 /// description of the `Nearest` rounding mode.
359 ///
360 /// $$
361 /// f(x,k,p) = \log_{2^k}(1+x)+\varepsilon.
362 /// $$
363 /// - If $\log_{2^k}(1+x)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
364 /// to be 0.
365 /// - If $\log_{2^k}(1+x)$ is finite and nonzero, then $|\varepsilon| \leq 2^{\lfloor\log_2
366 /// |\log_{2^k}(1+x)|\rfloor-p}$.
367 ///
368 /// If the output has a precision, it is `prec`.
369 ///
370 /// Special cases:
371 /// - $f(\text{NaN},k,p)=\text{NaN}$
372 /// - $f(\infty,k,p)=\infty$ if $k>0$, and $-\infty$ if $k<0$
373 /// - $f(-\infty,k,p)=\text{NaN}$
374 /// - $f(0.0,k,p)=0.0$ if $k>0$, and $-0.0$ if $k<0$
375 /// - $f(-0.0,k,p)=-0.0$ if $k>0$, and $0.0$ if $k<0$
376 /// - $f(-1.0,k,p)=-\infty$ if $k>0$, and $\infty$ if $k<0$
377 /// - $f(x,k,p)=\text{NaN}$ for $x<-1$
378 /// - $f(x,k,p)=m/k$ when $1+x=2^m$, rounded to precision $p$; the result is exact if and only
379 /// if $m/k$ is representable with precision $p$
380 ///
381 /// This function cannot overflow, but it can underflow:
382 /// - If $0<f(x,k,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
383 /// - If $2^{-2^{30}-1}<f(x,k,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
384 /// - If $-2^{-2^{30}-1}\leq f(x,k,p)<0$, $-0.0$ is returned instead.
385 /// - If $-2^{-2^{30}}<f(x,k,p)<-2^{-2^{30}-1}$, $-2^{-2^{30}}$ is returned instead.
386 ///
387 /// If you want to use a rounding mode other than `Nearest`, consider using
388 /// [`Float::log_base_power_of_2_1_plus_x_prec_round`] instead. If you know that your target
389 /// precision is the precision of the input, consider using
390 /// [`Float::log_base_power_of_2_1_plus_x`] instead.
391 ///
392 /// # Worst-case complexity
393 /// $T(n) = O(n (\log n)^2 \log\log n)$
394 ///
395 /// $M(n) = O(n (\log n)^2)$
396 ///
397 /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
398 ///
399 /// # Panics
400 /// Panics if `prec` is zero or if `pow` is zero (the base $2^0=1$ has no logarithm).
401 ///
402 /// # Examples
403 /// ```
404 /// use malachite_float::Float;
405 /// use std::cmp::Ordering::*;
406 ///
407 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
408 /// .0
409 /// .log_base_power_of_2_1_plus_x_prec(2, 20);
410 /// assert_eq!(log.to_string(), "1.729715");
411 /// assert_eq!(o, Less);
412 /// ```
413 #[inline]
414 pub fn log_base_power_of_2_1_plus_x_prec(self, pow: i64, prec: u64) -> (Self, Ordering) {
415 self.log_base_power_of_2_1_plus_x_prec_round(pow, prec, Nearest)
416 }
417
418 /// Computes $\log_{2^k}(1+x)$, where $x$ is a [`Float`] and the base is $2^k$ for some nonzero
419 /// integer $k$, rounding the result to the nearest value of the specified precision. The base's
420 /// exponent $k$ is `pow`, which may be negative. The [`Float`] is taken by reference. An
421 /// [`Ordering`] is also returned, indicating whether the rounded value is less than, equal to,
422 /// or greater than the exact value. Although `NaN`s are not comparable to any [`Float`],
423 /// whenever this function returns a `NaN` it also returns `Equal`.
424 ///
425 /// $\log_{2^k}(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, `NaN` is returned.
426 ///
427 /// If the logarithm is equidistant from two [`Float`]s with the specified precision, the
428 /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
429 /// description of the `Nearest` rounding mode.
430 ///
431 /// $$
432 /// f(x,k,p) = \log_{2^k}(1+x)+\varepsilon.
433 /// $$
434 /// - If $\log_{2^k}(1+x)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
435 /// to be 0.
436 /// - If $\log_{2^k}(1+x)$ is finite and nonzero, then $|\varepsilon| \leq 2^{\lfloor\log_2
437 /// |\log_{2^k}(1+x)|\rfloor-p}$.
438 ///
439 /// If the output has a precision, it is `prec`.
440 ///
441 /// Special cases:
442 /// - $f(\text{NaN},k,p)=\text{NaN}$
443 /// - $f(\infty,k,p)=\infty$ if $k>0$, and $-\infty$ if $k<0$
444 /// - $f(-\infty,k,p)=\text{NaN}$
445 /// - $f(0.0,k,p)=0.0$ if $k>0$, and $-0.0$ if $k<0$
446 /// - $f(-0.0,k,p)=-0.0$ if $k>0$, and $0.0$ if $k<0$
447 /// - $f(-1.0,k,p)=-\infty$ if $k>0$, and $\infty$ if $k<0$
448 /// - $f(x,k,p)=\text{NaN}$ for $x<-1$
449 /// - $f(x,k,p)=m/k$ when $1+x=2^m$, rounded to precision $p$; the result is exact if and only
450 /// if $m/k$ is representable with precision $p$
451 ///
452 /// This function cannot overflow, but it can underflow:
453 /// - If $0<f(x,k,p)\leq2^{-2^{30}-1}$, $0.0$ is returned instead.
454 /// - If $2^{-2^{30}-1}<f(x,k,p)<2^{-2^{30}}$, $2^{-2^{30}}$ is returned instead.
455 /// - If $-2^{-2^{30}-1}\leq f(x,k,p)<0$, $-0.0$ is returned instead.
456 /// - If $-2^{-2^{30}}<f(x,k,p)<-2^{-2^{30}-1}$, $-2^{-2^{30}}$ is returned instead.
457 ///
458 /// If you want to use a rounding mode other than `Nearest`, consider using
459 /// [`Float::log_base_power_of_2_1_plus_x_prec_round_ref`] instead. If you know that your target
460 /// precision is the precision of the input, consider using
461 /// `(&Float).log_base_power_of_2_1_plus_x()` instead.
462 ///
463 /// # Worst-case complexity
464 /// $T(n) = O(n (\log n)^2 \log\log n)$
465 ///
466 /// $M(n) = O(n (\log n)^2)$
467 ///
468 /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
469 ///
470 /// # Panics
471 /// Panics if `prec` is zero or if `pow` is zero (the base $2^0=1$ has no logarithm).
472 ///
473 /// # Examples
474 /// ```
475 /// use malachite_float::Float;
476 /// use std::cmp::Ordering::*;
477 ///
478 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
479 /// .0
480 /// .log_base_power_of_2_1_plus_x_prec_ref(2, 20);
481 /// assert_eq!(log.to_string(), "1.729715");
482 /// assert_eq!(o, Less);
483 /// ```
484 #[inline]
485 pub fn log_base_power_of_2_1_plus_x_prec_ref(&self, pow: i64, prec: u64) -> (Self, Ordering) {
486 self.log_base_power_of_2_1_plus_x_prec_round_ref(pow, prec, Nearest)
487 }
488
489 /// Computes $\log_{2^k}(1+x)$, where $x$ is a [`Float`] and the base is $2^k$ for some nonzero
490 /// integer $k$, rounding the result with the specified rounding mode. The base's exponent $k$
491 /// is `pow`, which may be negative. The [`Float`] is taken by value. An [`Ordering`] is also
492 /// returned, indicating whether the rounded value is less than, equal to, or greater than the
493 /// exact value. Although `NaN`s are not comparable to any [`Float`], whenever this function
494 /// returns a `NaN` it also returns `Equal`.
495 ///
496 /// $\log_{2^k}(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, `NaN` is returned.
497 ///
498 /// The precision of the output is the precision of the input. See [`RoundingMode`] for a
499 /// description of the possible rounding modes.
500 ///
501 /// $$
502 /// f(x,k,m) = \log_{2^k}(1+x)+\varepsilon.
503 /// $$
504 /// - If $\log_{2^k}(1+x)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
505 /// to be 0.
506 /// - If $\log_{2^k}(1+x)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon|
507 /// < 2^{\lfloor\log_2 |\log_{2^k}(1+x)|\rfloor-p+1}$, where $p$ is the precision of the
508 /// input.
509 /// - If $\log_{2^k}(1+x)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
510 /// 2^{\lfloor\log_2 |\log_{2^k}(1+x)|\rfloor-p}$, where $p$ is the precision of the input.
511 ///
512 /// If the output has a precision, it is the precision of the input.
513 ///
514 /// See the [`Float::log_base_power_of_2_1_plus_x_prec_round`] documentation for information on
515 /// special cases, overflow, and underflow.
516 ///
517 /// If you want to specify an output precision, consider using
518 /// [`Float::log_base_power_of_2_1_plus_x_prec_round`] instead. If you know you'll be using the
519 /// `Nearest` rounding mode, consider using [`Float::log_base_power_of_2_1_plus_x`] instead.
520 ///
521 /// # Worst-case complexity
522 /// $T(n) = O(n (\log n)^2 \log\log n)$
523 ///
524 /// $M(n) = O(n (\log n)^2)$
525 ///
526 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`.
527 ///
528 /// # Panics
529 /// Panics if `pow` is zero (the base $2^0=1$ has no logarithm), or if `rm` is `Exact` but the
530 /// result cannot be represented exactly with the input precision.
531 ///
532 /// # Examples
533 /// ```
534 /// use malachite_base::rounding_modes::RoundingMode::*;
535 /// use malachite_float::Float;
536 /// use std::cmp::Ordering::*;
537 ///
538 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
539 /// .0
540 /// .log_base_power_of_2_1_plus_x_round(2, Floor);
541 /// assert_eq!(log.to_string(), "1.729715809318648628099681523362");
542 /// assert_eq!(o, Less);
543 /// ```
544 #[inline]
545 pub fn log_base_power_of_2_1_plus_x_round(
546 self,
547 pow: i64,
548 rm: RoundingMode,
549 ) -> (Self, Ordering) {
550 let prec = self.significant_bits();
551 self.log_base_power_of_2_1_plus_x_prec_round(pow, prec, rm)
552 }
553
554 /// Computes $\log_{2^k}(1+x)$, where $x$ is a [`Float`] and the base is $2^k$ for some nonzero
555 /// integer $k$, rounding the result with the specified rounding mode. The base's exponent $k$
556 /// is `pow`, which may be negative. The [`Float`] is taken by reference. An [`Ordering`] is
557 /// also returned, indicating whether the rounded value is less than, equal to, or greater than
558 /// the exact value. Although `NaN`s are not comparable to any [`Float`], whenever this function
559 /// returns a `NaN` it also returns `Equal`.
560 ///
561 /// $\log_{2^k}(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, `NaN` is returned.
562 ///
563 /// The precision of the output is the precision of the input. See [`RoundingMode`] for a
564 /// description of the possible rounding modes.
565 ///
566 /// $$
567 /// f(x,k,m) = \log_{2^k}(1+x)+\varepsilon.
568 /// $$
569 /// - If $\log_{2^k}(1+x)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
570 /// to be 0.
571 /// - If $\log_{2^k}(1+x)$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon|
572 /// < 2^{\lfloor\log_2 |\log_{2^k}(1+x)|\rfloor-p+1}$, where $p$ is the precision of the
573 /// input.
574 /// - If $\log_{2^k}(1+x)$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
575 /// 2^{\lfloor\log_2 |\log_{2^k}(1+x)|\rfloor-p}$, where $p$ is the precision of the input.
576 ///
577 /// If the output has a precision, it is the precision of the input.
578 ///
579 /// See the [`Float::log_base_power_of_2_1_plus_x_prec_round`] documentation for information on
580 /// special cases, overflow, and underflow.
581 ///
582 /// If you want to specify an output precision, consider using
583 /// [`Float::log_base_power_of_2_1_plus_x_prec_round_ref`] instead. If you know you'll be using
584 /// the `Nearest` rounding mode, consider using `(&Float).log_base_power_of_2_1_plus_x()`
585 /// instead.
586 ///
587 /// # Worst-case complexity
588 /// $T(n) = O(n (\log n)^2 \log\log n)$
589 ///
590 /// $M(n) = O(n (\log n)^2)$
591 ///
592 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`.
593 ///
594 /// # Panics
595 /// Panics if `pow` is zero (the base $2^0=1$ has no logarithm), or if `rm` is `Exact` but the
596 /// result cannot be represented exactly with the input precision.
597 ///
598 /// # Examples
599 /// ```
600 /// use malachite_base::rounding_modes::RoundingMode::*;
601 /// use malachite_float::Float;
602 /// use std::cmp::Ordering::*;
603 ///
604 /// let (log, o) = Float::from_unsigned_prec(10u32, 100)
605 /// .0
606 /// .log_base_power_of_2_1_plus_x_round_ref(2, Floor);
607 /// assert_eq!(log.to_string(), "1.729715809318648628099681523362");
608 /// assert_eq!(o, Less);
609 /// ```
610 #[inline]
611 pub fn log_base_power_of_2_1_plus_x_round_ref(
612 &self,
613 pow: i64,
614 rm: RoundingMode,
615 ) -> (Self, Ordering) {
616 let prec = self.significant_bits();
617 self.log_base_power_of_2_1_plus_x_prec_round_ref(pow, prec, rm)
618 }
619
620 /// Computes $\log_{2^k}(1+x)$, where $x$ is a [`Float`] and the base is $2^k$ for some nonzero
621 /// integer $k$, in place, rounding the result to the specified precision and with the specified
622 /// rounding mode. The base's exponent $k$ is `pow`, which may be negative. An [`Ordering`] is
623 /// returned, indicating whether the rounded value is less than, equal to, or greater than the
624 /// exact value. Although `NaN`s are not comparable to any [`Float`], whenever this function
625 /// sets the [`Float`] to `NaN` it also returns `Equal`.
626 ///
627 /// $\log_{2^k}(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, the [`Float`] is set to
628 /// `NaN`.
629 ///
630 /// See [`RoundingMode`] for a description of the possible rounding modes.
631 ///
632 /// $$
633 /// x \gets \log_{2^k}(1+x)+\varepsilon.
634 /// $$
635 ///
636 /// If the output has a precision, it is `prec`.
637 ///
638 /// See the [`Float::log_base_power_of_2_1_plus_x_prec_round`] documentation for information on
639 /// special cases, overflow, and underflow.
640 ///
641 /// If you know you'll be using `Nearest`, consider using
642 /// [`Float::log_base_power_of_2_1_plus_x_prec_assign`] instead. If you know that your target
643 /// precision is the precision of the input, consider using
644 /// [`Float::log_base_power_of_2_1_plus_x_round_assign`] instead. If both of these things are
645 /// true, consider using [`Float::log_base_power_of_2_1_plus_x_assign`] instead.
646 ///
647 /// # Worst-case complexity
648 /// $T(n) = O(n (\log n)^2 \log\log n)$
649 ///
650 /// $M(n) = O(n (\log n)^2)$
651 ///
652 /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
653 ///
654 /// # Panics
655 /// Panics if `prec` is zero, if `pow` is zero (the base $2^0=1$ has no logarithm), or if `rm`
656 /// is `Exact` but the result cannot be represented exactly with the given precision.
657 ///
658 /// # Examples
659 /// ```
660 /// use malachite_base::rounding_modes::RoundingMode::*;
661 /// use malachite_float::Float;
662 /// use std::cmp::Ordering::*;
663 ///
664 /// let mut x = Float::from_unsigned_prec(10u32, 100).0;
665 /// assert_eq!(
666 /// x.log_base_power_of_2_1_plus_x_prec_round_assign(2, 20, Floor),
667 /// Less
668 /// );
669 /// assert_eq!(x.to_string(), "1.729715");
670 /// ```
671 #[inline]
672 pub fn log_base_power_of_2_1_plus_x_prec_round_assign(
673 &mut self,
674 pow: i64,
675 prec: u64,
676 rm: RoundingMode,
677 ) -> Ordering {
678 let (result, o) =
679 core::mem::take(self).log_base_power_of_2_1_plus_x_prec_round(pow, prec, rm);
680 *self = result;
681 o
682 }
683
684 /// Computes $\log_{2^k}(1+x)$, where $x$ is a [`Float`] and the base is $2^k$ for some nonzero
685 /// integer $k$, in place, rounding the result to the nearest value of the specified precision.
686 /// The base's exponent $k$ is `pow`, which may be negative. An [`Ordering`] is returned,
687 /// indicating whether the rounded value is less than, equal to, or greater than the exact
688 /// value. Although `NaN`s are not comparable to any [`Float`], whenever this function sets the
689 /// [`Float`] to `NaN` it also returns `Equal`.
690 ///
691 /// $\log_{2^k}(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, the [`Float`] is set to
692 /// `NaN`.
693 ///
694 /// If the logarithm is equidistant from two [`Float`]s with the specified precision, the
695 /// [`Float`] with fewer 1s in its binary expansion is chosen. See [`RoundingMode`] for a
696 /// description of the `Nearest` rounding mode.
697 ///
698 /// $$
699 /// x \gets \log_{2^k}(1+x)+\varepsilon.
700 /// $$
701 ///
702 /// If the output has a precision, it is `prec`.
703 ///
704 /// See the [`Float::log_base_power_of_2_1_plus_x_prec`] documentation for information on
705 /// special cases, overflow, and underflow.
706 ///
707 /// If you want to use a rounding mode other than `Nearest`, consider using
708 /// [`Float::log_base_power_of_2_1_plus_x_prec_round_assign`] instead. If you know that your
709 /// target precision is the precision of the input, consider using
710 /// [`Float::log_base_power_of_2_1_plus_x_assign`] instead.
711 ///
712 /// # Worst-case complexity
713 /// $T(n) = O(n (\log n)^2 \log\log n)$
714 ///
715 /// $M(n) = O(n (\log n)^2)$
716 ///
717 /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
718 ///
719 /// # Panics
720 /// Panics if `prec` is zero or if `pow` is zero (the base $2^0=1$ has no logarithm).
721 ///
722 /// # Examples
723 /// ```
724 /// use malachite_float::Float;
725 /// use std::cmp::Ordering::*;
726 ///
727 /// let mut x = Float::from_unsigned_prec(10u32, 100).0;
728 /// assert_eq!(x.log_base_power_of_2_1_plus_x_prec_assign(2, 20), Less);
729 /// assert_eq!(x.to_string(), "1.729715");
730 /// ```
731 #[inline]
732 pub fn log_base_power_of_2_1_plus_x_prec_assign(&mut self, pow: i64, prec: u64) -> Ordering {
733 self.log_base_power_of_2_1_plus_x_prec_round_assign(pow, prec, Nearest)
734 }
735
736 /// Computes $\log_{2^k}(1+x)$, where $x$ is a [`Float`] and the base is $2^k$ for some nonzero
737 /// integer $k$, in place, rounding the result with the specified rounding mode. The base's
738 /// exponent $k$ is `pow`, which may be negative. An [`Ordering`] is returned, indicating
739 /// whether the rounded value is less than, equal to, or greater than the exact value. Although
740 /// `NaN`s are not comparable to any [`Float`], whenever this function sets the [`Float`] to
741 /// `NaN` it also returns `Equal`.
742 ///
743 /// $\log_{2^k}(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, the [`Float`] is set to
744 /// `NaN`.
745 ///
746 /// The precision of the output is the precision of the input. See [`RoundingMode`] for a
747 /// description of the possible rounding modes.
748 ///
749 /// $$
750 /// x \gets \log_{2^k}(1+x)+\varepsilon.
751 /// $$
752 ///
753 /// If the output has a precision, it is the precision of the input.
754 ///
755 /// See the [`Float::log_base_power_of_2_1_plus_x_round`] documentation for information on
756 /// special cases, overflow, and underflow.
757 ///
758 /// If you want to specify an output precision, consider using
759 /// [`Float::log_base_power_of_2_1_plus_x_prec_round_assign`] instead. If you know you'll be
760 /// using the `Nearest` rounding mode, consider using
761 /// [`Float::log_base_power_of_2_1_plus_x_assign`] instead.
762 ///
763 /// # Worst-case complexity
764 /// $T(n) = O(n (\log n)^2 \log\log n)$
765 ///
766 /// $M(n) = O(n (\log n)^2)$
767 ///
768 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`.
769 ///
770 /// # Panics
771 /// Panics if `pow` is zero (the base $2^0=1$ has no logarithm), or if `rm` is `Exact` but the
772 /// result cannot be represented exactly with the input precision.
773 ///
774 /// # Examples
775 /// ```
776 /// use malachite_base::rounding_modes::RoundingMode::*;
777 /// use malachite_float::Float;
778 /// use std::cmp::Ordering::*;
779 ///
780 /// let mut x = Float::from_unsigned_prec(10u32, 100).0;
781 /// assert_eq!(x.log_base_power_of_2_1_plus_x_round_assign(2, Floor), Less);
782 /// assert_eq!(x.to_string(), "1.729715809318648628099681523362");
783 /// ```
784 #[inline]
785 pub fn log_base_power_of_2_1_plus_x_round_assign(
786 &mut self,
787 pow: i64,
788 rm: RoundingMode,
789 ) -> Ordering {
790 let prec = self.significant_bits();
791 self.log_base_power_of_2_1_plus_x_prec_round_assign(pow, prec, rm)
792 }
793}
794
795impl LogBasePowerOf2Of1PlusX<i64> for Float {
796 type Output = Self;
797
798 /// Computes $\log_{2^k}(1+x)$, where $x$ is a [`Float`] and the base is $2^k$ for some nonzero
799 /// integer $k$, taking it by value. The base's exponent $k$ is `pow`, which may be negative.
800 ///
801 /// If the output has a precision, it is the precision of the input. If the logarithm is
802 /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in
803 /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
804 /// rounding mode.
805 ///
806 /// $\log_{2^k}(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, `NaN` is returned.
807 ///
808 /// $$
809 /// f(x,k) = \log_{2^k}(1+x)+\varepsilon.
810 /// $$
811 /// - If $\log_{2^k}(1+x)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
812 /// to be 0.
813 /// - If $\log_{2^k}(1+x)$ is finite and nonzero, then $|\varepsilon| \leq 2^{\lfloor\log_2
814 /// |\log_{2^k}(1+x)|\rfloor-p}$, where $p$ is the precision of the input.
815 ///
816 /// See the [`Float::log_base_power_of_2_1_plus_x_prec_round`] documentation for information on
817 /// special cases, overflow, and underflow.
818 ///
819 /// If you want to use a rounding mode other than `Nearest`, consider using
820 /// [`Float::log_base_power_of_2_1_plus_x_round`] instead. If you want to specify the output
821 /// precision, consider using [`Float::log_base_power_of_2_1_plus_x_prec`]. If you want both of
822 /// these things, consider using [`Float::log_base_power_of_2_1_plus_x_prec_round`].
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 `self.get_prec()`.
830 ///
831 /// # Panics
832 /// Panics if `pow` is zero (the base $2^0=1$ has no logarithm).
833 ///
834 /// # Examples
835 /// ```
836 /// use malachite_base::num::arithmetic::traits::LogBasePowerOf2Of1PlusX;
837 /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity};
838 /// use malachite_float::Float;
839 ///
840 /// assert!(Float::NAN.log_base_power_of_2_1_plus_x(2).is_nan());
841 /// assert_eq!(
842 /// Float::INFINITY.log_base_power_of_2_1_plus_x(2),
843 /// Float::INFINITY
844 /// );
845 /// assert!(Float::NEGATIVE_INFINITY
846 /// .log_base_power_of_2_1_plus_x(2)
847 /// .is_nan());
848 /// assert_eq!(
849 /// Float::from_unsigned_prec(10u32, 100)
850 /// .0
851 /// .log_base_power_of_2_1_plus_x(2)
852 /// .to_string(),
853 /// "1.729715809318648628099681523362"
854 /// );
855 /// ```
856 #[inline]
857 fn log_base_power_of_2_1_plus_x(self, pow: i64) -> Self {
858 let prec = self.significant_bits();
859 self.log_base_power_of_2_1_plus_x_prec_round(pow, prec, Nearest)
860 .0
861 }
862}
863
864impl LogBasePowerOf2Of1PlusX<i64> for &Float {
865 type Output = Float;
866
867 /// Computes $\log_{2^k}(1+x)$, where $x$ is a [`Float`] and the base is $2^k$ for some nonzero
868 /// integer $k$, taking it by reference. The base's exponent $k$ is `pow`, which may be
869 /// negative.
870 ///
871 /// If the output has a precision, it is the precision of the input. If the logarithm is
872 /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in
873 /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
874 /// rounding mode.
875 ///
876 /// $\log_{2^k}(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, `NaN` is returned.
877 ///
878 /// $$
879 /// f(x,k) = \log_{2^k}(1+x)+\varepsilon.
880 /// $$
881 /// - If $\log_{2^k}(1+x)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
882 /// to be 0.
883 /// - If $\log_{2^k}(1+x)$ is finite and nonzero, then $|\varepsilon| \leq 2^{\lfloor\log_2
884 /// |\log_{2^k}(1+x)|\rfloor-p}$, where $p$ is the precision of the input.
885 ///
886 /// See the [`Float::log_base_power_of_2_1_plus_x_prec_round`] documentation for information on
887 /// special cases, overflow, and underflow.
888 ///
889 /// If you want to use a rounding mode other than `Nearest`, consider using
890 /// [`Float::log_base_power_of_2_1_plus_x_round_ref`] instead. If you want to specify the output
891 /// precision, consider using [`Float::log_base_power_of_2_1_plus_x_prec_ref`]. If you want both
892 /// of these things, consider using [`Float::log_base_power_of_2_1_plus_x_prec_round_ref`].
893 ///
894 /// # Worst-case complexity
895 /// $T(n) = O(n (\log n)^2 \log\log n)$
896 ///
897 /// $M(n) = O(n (\log n)^2)$
898 ///
899 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`.
900 ///
901 /// # Panics
902 /// Panics if `pow` is zero (the base $2^0=1$ has no logarithm).
903 ///
904 /// # Examples
905 /// ```
906 /// use malachite_base::num::arithmetic::traits::LogBasePowerOf2Of1PlusX;
907 /// use malachite_base::num::basic::traits::{Infinity, NaN, NegativeInfinity};
908 /// use malachite_float::Float;
909 ///
910 /// assert!((&Float::NAN).log_base_power_of_2_1_plus_x(2).is_nan());
911 /// assert_eq!(
912 /// (&Float::INFINITY).log_base_power_of_2_1_plus_x(2),
913 /// Float::INFINITY
914 /// );
915 /// assert!((&Float::NEGATIVE_INFINITY)
916 /// .log_base_power_of_2_1_plus_x(2)
917 /// .is_nan());
918 /// assert_eq!(
919 /// (&Float::from_unsigned_prec(10u32, 100).0)
920 /// .log_base_power_of_2_1_plus_x(2)
921 /// .to_string(),
922 /// "1.729715809318648628099681523362"
923 /// );
924 /// ```
925 #[inline]
926 fn log_base_power_of_2_1_plus_x(self, pow: i64) -> Float {
927 let prec = self.significant_bits();
928 self.log_base_power_of_2_1_plus_x_prec_round_ref(pow, prec, Nearest)
929 .0
930 }
931}
932
933impl LogBasePowerOf2Of1PlusXAssign<i64> for Float {
934 /// Computes $\log_{2^k}(1+x)$, where $x$ is a [`Float`] and the base is $2^k$ for some nonzero
935 /// integer $k$, in place. The base's exponent $k$ is `pow`, which may be negative.
936 ///
937 /// If the output has a precision, it is the precision of the input. If the logarithm is
938 /// equidistant from two [`Float`]s with the specified precision, the [`Float`] with fewer 1s in
939 /// its binary expansion is chosen. See [`RoundingMode`] for a description of the `Nearest`
940 /// rounding mode.
941 ///
942 /// $\log_{2^k}(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, the [`Float`] is set to
943 /// `NaN`.
944 ///
945 /// $$
946 /// x \gets \log_{2^k}(1+x)+\varepsilon.
947 /// $$
948 /// - If $\log_{2^k}(1+x)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed
949 /// to be 0.
950 /// - If $\log_{2^k}(1+x)$ is finite and nonzero, then $|\varepsilon| \leq 2^{\lfloor\log_2
951 /// |\log_{2^k}(1+x)|\rfloor-p}$, where $p$ is the precision of the input.
952 ///
953 /// See the [`Float::log_base_power_of_2_1_plus_x`] documentation for information on special
954 /// cases, overflow, and underflow.
955 ///
956 /// If you want to use a rounding mode other than `Nearest`, consider using
957 /// [`Float::log_base_power_of_2_1_plus_x_round_assign`] instead. If you want to specify the
958 /// output precision, consider using [`Float::log_base_power_of_2_1_plus_x_prec_assign`]. If you
959 /// want both of these things, consider using
960 /// [`Float::log_base_power_of_2_1_plus_x_prec_round_assign`].
961 ///
962 /// # Worst-case complexity
963 /// $T(n) = O(n (\log n)^2 \log\log n)$
964 ///
965 /// $M(n) = O(n (\log n)^2)$
966 ///
967 /// where $T$ is time, $M$ is additional memory, and $n$ is `self.get_prec()`.
968 ///
969 /// # Panics
970 /// Panics if `pow` is zero (the base $2^0=1$ has no logarithm).
971 ///
972 /// # Examples
973 /// ```
974 /// use malachite_base::num::arithmetic::traits::LogBasePowerOf2Of1PlusXAssign;
975 /// use malachite_base::num::basic::traits::{Infinity, NaN};
976 /// use malachite_float::Float;
977 ///
978 /// let mut x = Float::NAN;
979 /// x.log_base_power_of_2_1_plus_x_assign(2);
980 /// assert!(x.is_nan());
981 ///
982 /// let mut x = Float::INFINITY;
983 /// x.log_base_power_of_2_1_plus_x_assign(2);
984 /// assert_eq!(x, Float::INFINITY);
985 ///
986 /// let mut x = Float::from_unsigned_prec(10u32, 100).0;
987 /// x.log_base_power_of_2_1_plus_x_assign(2);
988 /// assert_eq!(x.to_string(), "1.729715809318648628099681523362");
989 /// ```
990 #[inline]
991 fn log_base_power_of_2_1_plus_x_assign(&mut self, pow: i64) {
992 let prec = self.significant_bits();
993 self.log_base_power_of_2_1_plus_x_prec_round_assign(pow, prec, Nearest);
994 }
995}
996
997/// Computes $\log_{2^k}(1+x)$, the base-$2^k$ logarithm of one plus a primitive float, where the
998/// base is $2^k$ for some nonzero integer $k$. The exponent $k$ is `pow`, which may be negative.
999/// Using this function is more accurate than computing the logarithm using the standard library,
1000/// both because $1+x$ may not be representable as a primitive float and because the standard
1001/// library's `log2` is not always correctly rounded.
1002///
1003/// $\log_{2^k}(1+x)$ is undefined for $x<-1$, so whenever $x<-1$, `NaN` is returned.
1004///
1005/// $$
1006/// f(x,k) = \log_{2^k}(1+x)+\varepsilon.
1007/// $$
1008/// - If $\log_{2^k}(1+x)$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to
1009/// be 0.
1010/// - If $\log_{2^k}(1+x)$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2
1011/// |\log_{2^k}(1+x)|\rfloor-p}$, where $p$ is precision of the output (typically 24 if `T` is a
1012/// [`f32`] and 53 if `T` is a [`f64`], but less if the output is subnormal).
1013///
1014/// Special cases:
1015/// - $f(\text{NaN},k)=\text{NaN}$
1016/// - $f(\infty,k)=\infty$ if $k>0$, and $-\infty$ if $k<0$
1017/// - $f(-\infty,k)=\text{NaN}$
1018/// - $f(0.0,k)=0.0$ if $k>0$, and $-0.0$ if $k<0$
1019/// - $f(-0.0,k)=-0.0$ if $k>0$, and $0.0$ if $k<0$
1020/// - $f(-1.0,k)=-\infty$ if $k>0$, and $\infty$ if $k<0$
1021/// - $f(x,k)=\text{NaN}$ for $x<-1$
1022///
1023/// This function can underflow (to a subnormal or zero) when $x$ is close to zero and $|k|$ is
1024/// large, but it cannot overflow.
1025///
1026/// # Worst-case complexity
1027/// Constant time and additional memory.
1028///
1029/// # Panics
1030/// Panics if `pow` is zero (the base $2^0=1$ has no logarithm).
1031///
1032/// # Examples
1033/// ```
1034/// use malachite_base::num::basic::traits::NegativeInfinity;
1035/// use malachite_base::num::float::NiceFloat;
1036/// use malachite_float::arithmetic::log_base_power_of_2_1_plus_x::*;
1037///
1038/// assert!(primitive_float_log_base_power_of_2_1_plus_x(f32::NAN, 2).is_nan());
1039/// assert_eq!(
1040/// NiceFloat(primitive_float_log_base_power_of_2_1_plus_x(
1041/// f32::INFINITY,
1042/// 2
1043/// )),
1044/// NiceFloat(f32::INFINITY)
1045/// );
1046/// assert_eq!(
1047/// NiceFloat(primitive_float_log_base_power_of_2_1_plus_x(-1.0f32, 2)),
1048/// NiceFloat(f32::NEGATIVE_INFINITY)
1049/// );
1050/// assert!(primitive_float_log_base_power_of_2_1_plus_x(-2.0f32, 2).is_nan());
1051/// // log_4(1 + 15) = log_4(16) = 2
1052/// assert_eq!(
1053/// NiceFloat(primitive_float_log_base_power_of_2_1_plus_x(15.0f32, 2)),
1054/// NiceFloat(2.0)
1055/// );
1056/// // log_4(1 + 7) = log_4(8) = 3/2
1057/// assert_eq!(
1058/// NiceFloat(primitive_float_log_base_power_of_2_1_plus_x(7.0f32, 2)),
1059/// NiceFloat(1.5)
1060/// );
1061/// // log_8(1 + 63) = log_8(64) = 2
1062/// assert_eq!(
1063/// NiceFloat(primitive_float_log_base_power_of_2_1_plus_x(63.0f32, 3)),
1064/// NiceFloat(2.0)
1065/// );
1066/// // log_4(1 + 9) = log_4(10)
1067/// assert_eq!(
1068/// NiceFloat(primitive_float_log_base_power_of_2_1_plus_x(9.0f32, 2)),
1069/// NiceFloat(1.660964)
1070/// );
1071/// // log_(1/2)(1 + 7) = log_(1/2)(8) = -3
1072/// assert_eq!(
1073/// NiceFloat(primitive_float_log_base_power_of_2_1_plus_x(7.0f32, -1)),
1074/// NiceFloat(-3.0)
1075/// );
1076/// ```
1077#[inline]
1078#[allow(clippy::type_repetition_in_bounds)]
1079pub fn primitive_float_log_base_power_of_2_1_plus_x<T: PrimitiveFloat>(x: T, pow: i64) -> T
1080where
1081 Float: From<T> + PartialOrd<T>,
1082 for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
1083{
1084 emulate_float_to_float_fn(
1085 |x, prec| Float::log_base_power_of_2_1_plus_x_prec(x, pow, prec),
1086 x,
1087 )
1088}