malachite_float/float/arithmetic/log_base_float_base.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};
10use crate::float::arithmetic::ln::{SliverOfOne, sliver_of_one};
11use crate::float::arithmetic::log_base::{
12 dyadic_log_of_root, dyadic_primitive_root, odd_significand_and_exponent,
13};
14use crate::float::basic::extended::ExtendedFloat;
15use crate::{
16 Float, emulate_float_float_to_float_fn, float_infinity, float_nan, float_negative_infinity,
17};
18use core::cmp::Ordering::{self, *};
19use malachite_base::num::arithmetic::traits::{CeilingLogBase2, LogBase, LogBaseAssign};
20use malachite_base::num::basic::floats::PrimitiveFloat;
21use malachite_base::num::basic::integers::PrimitiveInt;
22use malachite_base::num::basic::traits::{NegativeZero, Zero as ZeroTrait};
23use malachite_base::num::conversion::traits::{ExactFrom, RoundingFrom};
24use malachite_base::num::logic::traits::SignificantBits;
25use malachite_base::rounding_modes::RoundingMode::{self, *};
26use malachite_nz::natural::arithmetic::float_extras::float_can_round;
27use malachite_nz::platform::Limb;
28use malachite_q::Rational;
29
30// Returns `Some(log_base(x))` when it is rational, and `None` when it is irrational. The inputs `x`
31// and `base` must both be finite, positive, and not equal to 1.
32//
33// `log_base(x)` is rational exactly when `x` and `base` are commensurable (both powers of a common
34// rational). Both are dyadic, so this reuses `rational_log_base_rational_rational_base` on their
35// exact `Rational` values; for a base in (0, 1) -- where `Rational::checked_log_base` requires a
36// base above 1 -- the identity `log_b(x) = -log_{1/b}(x)` reduces to a base above 1.
37//
38// Detecting these rational results up front is essential: the Ziv loop could never certify an
39// exactly-representable one. The check is balloon-safe: it materializes `x` and `base` as
40// `Rational`s only when their exponents and precisions are within `64 * prec`.
41pub(crate) fn log_base_float_base_rational(x: &Float, base: &Float) -> Option<Rational> {
42 // Both x and the base are dyadic: the base's primitive root comes from its odd significand and
43 // exponent, and x is matched against it on its own odd significand and exponent, so neither is
44 // ever materialized as a `Rational` (their exponents may be extreme, making the integer forms
45 // enormous even though the Floats are small). No size cutoff: skipping the check when the
46 // result is exactly representable (such as `log_4` of the smallest positive Float, `-2^29`)
47 // would leave the Ziv loop unable to terminate.
48 let (s_b, t_b) = odd_significand_and_exponent(base);
49 let (z, h, e_base) = dyadic_primitive_root(&s_b, t_b);
50 let (s, t) = odd_significand_and_exponent(x);
51 let m = dyadic_log_of_root(&s, t, z, &h)?;
52 Some(Rational::from_signeds(m, i64::exact_from(e_base)))
53}
54
55// The computation of log_base(x) for a `Float` base is done by log_base(x) = log_2(x) /
56// log_2(base). The inputs are finite, positive, and not equal to 1.
57//
58// Both logarithms are ordinary, correctly-rounded `Float`s (a `Float` operand cannot be close
59// enough to 1 to make its `log_2` underflow at any practical precision), but their quotient can
60// overflow (base near 1, so `log_2(base)` is tiny) or underflow (x near 1). So the operands are
61// wrapped as `ExtendedFloat`s, divided in the extended exponent range, and converted back with a
62// single `into_float_helper` clamp. A base in (0, 1) gives a negative `log_2(base)`, so the
63// division yields the (sign-flipped) result for free.
64fn log_base_float_base_normal(
65 x: &Float,
66 base: &Float,
67 prec: u64,
68 rm: RoundingMode,
69) -> (Float, Ordering) {
70 // log_base(1) = 0, with the sign of 1 / log_2(base): positive for base > 1, negative for a base
71 // in (0, 1).
72 if *x == 1u32 {
73 return if *base < 1u32 {
74 (Float::NEGATIVE_ZERO, Equal)
75 } else {
76 (Float::ZERO, Equal)
77 };
78 }
79 // If log_base(x) is rational -- x and base commensurable -- compute it directly. This includes
80 // exactly-representable results (which the Ziv loop could never certify) as well as
81 // non-representable rationals (cheaper and exact this way).
82 if let Some(q) = log_base_float_base_rational(x, base) {
83 return Float::from_rational_prec_round(q, prec, rm);
84 }
85 // log_base(x) for x in a sliver of 1 can fall below the smallest positive Float; the 1-plus-x
86 // form handles that underflow region.
87 match sliver_of_one(x) {
88 SliverOfOne::Representable(d) => {
89 return d.log_base_float_base_1_plus_x_prec_round(base, prec, rm);
90 }
91 SliverOfOne::Underflow => {
92 return Float::log_base_rational_float_base_prec_round(
93 Rational::exact_from(x),
94 base.clone(),
95 prec,
96 rm,
97 );
98 }
99 SliverOfOne::No => {}
100 }
101 // The result is irrational, so it is never exactly representable.
102 assert_ne!(rm, Exact, "Inexact log_base_float_base");
103 // The initial slack keeps working_prec at least 7, so the working_prec - 6 below stays
104 // positive.
105 let mut working_prec = prec + 6 + prec.ceiling_log_base_2();
106 let mut increment = Limb::WIDTH;
107 loop {
108 // log_2(x) and log_2(base), correctly rounded; both finite and nonzero (x, base positive
109 // and not 1), neither underflowing, so the ordinary logs wrapped as ExtendedFloats suffice.
110 let num = ExtendedFloat::from(x.log_base_2_prec_ref(working_prec).0);
111 let den = ExtendedFloat::from(base.log_base_2_prec_ref(working_prec).0);
112 // log_2(x) / log_2(base) in the extended range; cannot overflow or underflow here.
113 let quotient = num.div_prec_val_ref(&den, working_prec).0;
114 // Two correctly-rounded logs (<= 1/2 ulp each) and the division (<= 1/2 ulp) give under 2
115 // ulps total; working_prec - 6 correct bits comfortably suffice for the rounding test.
116 if float_can_round(
117 quotient.x.significand_ref().unwrap(),
118 working_prec - 6,
119 prec,
120 rm,
121 ) {
122 // Round the mantissa to prec, then place the extended exponent, clamping once to the
123 // Float range as the rounding mode dictates.
124 let (rounded, o) = Float::from_float_prec_round(quotient.x, prec, rm);
125 let mut result = ExtendedFloat::from(rounded);
126 result.exp = result.exp.checked_add(quotient.exp).unwrap();
127 return result.into_float_helper(prec, rm, o);
128 }
129 // Increase the precision.
130 working_prec += increment;
131 increment = working_prec >> 1;
132 }
133}
134
135// Computes log_base(x) = ln(x) / ln(base) for `Float` `x` and `base`, following IEEE division of
136// the natural logs for every special case (so the function is total: no input value panics).
137fn log_base_float_base_helper(
138 x: &Float,
139 base: &Float,
140 prec: u64,
141 rm: RoundingMode,
142) -> (Float, Ordering) {
143 // ln of either operand is NaN: x or base is NaN, or (below) negative.
144 if x.is_nan() || base.is_nan() {
145 return (float_nan!(), Equal);
146 }
147 // ln(base) is NaN for a negative base (negative finite or -infinity).
148 if *base < 0u32 {
149 return (float_nan!(), Equal);
150 }
151 // ln(x) is NaN for a negative x.
152 if *x < 0u32 {
153 return (float_nan!(), Equal);
154 }
155 // x and base are each now +infinity, zero, or positive finite.
156 if base.is_infinite() {
157 // ln(base) = +infinity. ln(x) / +infinity = 0 for finite x (NaN for an infinite or zero x).
158 if x.is_infinite() || *x == 0u32 {
159 return (float_nan!(), Equal);
160 }
161 // 0, signed like ln(x): +0 for x >= 1, -0 for 0 < x < 1.
162 return if *x < 1u32 {
163 (Float::NEGATIVE_ZERO, Equal)
164 } else {
165 (Float::ZERO, Equal)
166 };
167 }
168 if *base == 0u32 {
169 // ln(base) = -infinity. ln(x) / -infinity = 0 for finite x (NaN for an infinite or zero x),
170 // sign-flipped: -0 for x >= 1, +0 for 0 < x < 1.
171 if x.is_infinite() || *x == 0u32 {
172 return (float_nan!(), Equal);
173 }
174 return if *x < 1u32 {
175 (Float::ZERO, Equal)
176 } else {
177 (Float::NEGATIVE_ZERO, Equal)
178 };
179 }
180 // base is positive finite.
181 if *base == 1u32 {
182 // ln(base) = +0. ln(x) / +0 = +-infinity by the sign of ln(x), or NaN for ln(x) = +-0.
183 if x.is_infinite() {
184 return (float_infinity!(), Equal); // ln(+inf) = +inf
185 }
186 if *x == 0u32 {
187 return (float_negative_infinity!(), Equal); // ln(0) = -inf
188 }
189 return if *x == 1u32 {
190 (float_nan!(), Equal) // +0 / +0
191 } else if *x > 1u32 {
192 (float_infinity!(), Equal)
193 } else {
194 (float_negative_infinity!(), Equal)
195 };
196 }
197 // base is positive finite and not 1.
198 if x.is_infinite() {
199 // ln(x) = +infinity. +infinity / ln(base): +infinity for base > 1, -infinity for base < 1.
200 return if *base < 1u32 {
201 (float_negative_infinity!(), Equal)
202 } else {
203 (float_infinity!(), Equal)
204 };
205 }
206 if *x == 0u32 {
207 // ln(x) = -infinity. -infinity / ln(base): -infinity for base > 1, +infinity for base < 1.
208 return if *base < 1u32 {
209 (float_infinity!(), Equal)
210 } else {
211 (float_negative_infinity!(), Equal)
212 };
213 }
214 // x and base are both positive finite, with base not 1.
215 log_base_float_base_normal(x, base, prec, rm)
216}
217
218impl Float {
219 /// Computes $\log_b x$, where $x$ and the base $b$ are both [`Float`]s, rounding the result to
220 /// the specified precision and with the specified rounding mode. The [`Float`] is taken by
221 /// value and the base by reference. An [`Ordering`] is also returned, indicating whether the
222 /// rounded value is less than, equal to, or greater than the exact value. Although `NaN`s are
223 /// not comparable to any [`Float`], whenever this function returns a `NaN` it also returns
224 /// `Equal`.
225 ///
226 /// Unlike the integer- and rational-base logarithms, the base may be any [`Float`]: the
227 /// function is defined as $\ln x / \ln b$ for every pair of [`Float`]s, applying IEEE division
228 /// to the natural logs, and never panics on an input value. In particular a base in $(0,1)$
229 /// gives a (sign-flipped) logarithm, and the non-normal and degenerate bases follow the limits
230 /// below.
231 ///
232 /// This computes $\log_2 x / \log_2 b$, wrapping both logs in an extended exponent range so
233 /// that the quotient may overflow (base near 1) or underflow (x near 1) and be clamped exactly
234 /// once.
235 ///
236 /// See [`RoundingMode`] for a description of the possible rounding modes.
237 ///
238 /// $$
239 /// f(x,b,p,m) = \log_b x+\varepsilon.
240 /// $$
241 /// - If $\log_b x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be
242 /// 0.
243 /// - If $\log_b x$ is finite and nonzero, and $m$ is not `Nearest`, then $|\varepsilon| <
244 /// 2^{\lfloor\log_2 |\log_b x|\rfloor-p+1}$.
245 /// - If $\log_b x$ is finite and nonzero, and $m$ is `Nearest`, then $|\varepsilon| \leq
246 /// 2^{\lfloor\log_2 |\log_b x|\rfloor-p}$.
247 ///
248 /// If the output has a precision, it is `prec`.
249 ///
250 /// Special cases (with $b$ the base):
251 /// - $f(\text{NaN},b,p,m)=\text{NaN}$, and $f(x,\text{NaN},p,m)=\text{NaN}$
252 /// - $f(x,b,p,m)=\text{NaN}$ for $x<0$ or $b<0$ (including $\pm\infty$ where indicated below)
253 /// - $f(\infty,b,p,m)=\infty$ for $b>1$, and $-\infty$ for $0\leq b<1$
254 /// - $f(\pm0.0,b,p,m)=-\infty$ for $b>1$, and $\infty$ for $0<b<1$
255 /// - $f(1.0,b,p,m)=0$ (with the sign of $1/\ln b$)
256 /// - $f(x,\infty,p,m)=0$ for finite $x>0$ (and $\text{NaN}$ for $x\in\{\pm\infty,\pm0.0\}$)
257 /// - $f(x,\pm0.0,p,m)=0$ for finite $x>0$ (and $\text{NaN}$ for $x\in\{\pm\infty,\pm0.0\}$)
258 /// - $f(x,1.0,p,m)=\infty$ for $x>1$ or $x=\infty$, $-\infty$ for $0\leq x<1$, and $\text{NaN}$
259 /// for $x=1$
260 /// - $f(g^a,g^e,p,m)=a/e$ for a common rational $g$, rounded to precision $p$; the result is
261 /// exact if and only if $a/e$ is representable with precision $p$ (for example $\log_4
262 /// 8=3/2$)
263 ///
264 /// This function can both overflow (for a base near 1) and underflow (for an $x$ near 1).
265 ///
266 /// # Worst-case complexity
267 /// $T(n) = O(n (\log n)^2 \log\log n)$
268 ///
269 /// $M(n) = O(n (\log n)^2)$
270 ///
271 /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
272 ///
273 /// # Panics
274 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
275 /// with the given precision.
276 ///
277 /// # Examples
278 /// ```
279 /// use malachite_base::rounding_modes::RoundingMode::*;
280 /// use malachite_float::Float;
281 /// use std::cmp::Ordering::*;
282 ///
283 /// let (log, o) = Float::from(8).log_base_float_base_prec_round(&Float::from(4), 10, Exact);
284 /// assert_eq!(log.to_string(), "1.5000"); // log_4(8) = 3/2
285 /// assert_eq!(o, Equal);
286 ///
287 /// let (log, o) = Float::from(4).log_base_float_base_prec_round(&Float::from(0.5), 10, Exact);
288 /// assert_eq!(log.to_string(), "-2.0000"); // log_{1/2}(4) = -2
289 /// assert_eq!(o, Equal);
290 /// ```
291 #[inline]
292 pub fn log_base_float_base_prec_round(
293 self,
294 base: &Self,
295 prec: u64,
296 rm: RoundingMode,
297 ) -> (Self, Ordering) {
298 assert_ne!(prec, 0);
299 log_base_float_base_helper(&self, base, prec, rm)
300 }
301
302 /// Computes $\log_b x$, where $x$ and the base $b$ are both [`Float`]s, rounding the result to
303 /// the specified precision and with the specified rounding mode. Both are taken by reference.
304 /// An [`Ordering`] is also returned, indicating whether the rounded value is less than, equal
305 /// to, or greater than the exact value.
306 ///
307 /// See [`Float::log_base_float_base_prec_round`] for details, special cases, and a description
308 /// of the rounding behavior.
309 ///
310 /// # Worst-case complexity
311 /// $T(n) = O(n (\log n)^2 \log\log n)$
312 ///
313 /// $M(n) = O(n (\log n)^2)$
314 ///
315 /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
316 ///
317 /// # Panics
318 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
319 /// with the given precision.
320 ///
321 /// # Examples
322 /// ```
323 /// use malachite_base::rounding_modes::RoundingMode::*;
324 /// use malachite_float::Float;
325 /// use std::cmp::Ordering::*;
326 ///
327 /// let (log, o) =
328 /// (&Float::from(8)).log_base_float_base_prec_round_ref(&Float::from(2), 10, Exact);
329 /// assert_eq!(log.to_string(), "3.0000"); // log_2(8) = 3
330 /// assert_eq!(o, Equal);
331 ///
332 /// let (log, o) =
333 /// (&Float::from(2)).log_base_float_base_prec_round_ref(&Float::from(4), 10, Exact);
334 /// assert_eq!(log.to_string(), "0.50000"); // log_4(2) = 1/2
335 /// assert_eq!(o, Equal);
336 /// ```
337 #[inline]
338 pub fn log_base_float_base_prec_round_ref(
339 &self,
340 base: &Self,
341 prec: u64,
342 rm: RoundingMode,
343 ) -> (Self, Ordering) {
344 assert_ne!(prec, 0);
345 log_base_float_base_helper(self, base, prec, rm)
346 }
347
348 /// Computes $\log_b x$, where $x$ and the base $b$ are both [`Float`]s, rounding the result to
349 /// the nearest value of the specified precision. The [`Float`] is taken by value and the base
350 /// by reference. An [`Ordering`] is also returned.
351 ///
352 /// See [`Float::log_base_float_base_prec_round`] for details and special cases.
353 ///
354 /// # Worst-case complexity
355 /// $T(n) = O(n (\log n)^2 \log\log n)$
356 ///
357 /// $M(n) = O(n (\log n)^2)$
358 ///
359 /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
360 ///
361 /// # Panics
362 /// Panics if `prec` is zero.
363 ///
364 /// # Examples
365 /// ```
366 /// use malachite_float::Float;
367 /// use std::cmp::Ordering::*;
368 ///
369 /// let (log, o) = Float::from(8).log_base_float_base_prec(&Float::from(4), 10);
370 /// assert_eq!(log.to_string(), "1.5000"); // log_4(8) = 3/2
371 /// assert_eq!(o, Equal);
372 /// ```
373 #[inline]
374 pub fn log_base_float_base_prec(self, base: &Self, prec: u64) -> (Self, Ordering) {
375 self.log_base_float_base_prec_round(base, prec, Nearest)
376 }
377
378 /// Computes $\log_b x$, where $x$ and the base $b$ are both [`Float`]s, rounding the result to
379 /// the nearest value of the specified precision. Both are taken by reference. An [`Ordering`]
380 /// is also returned.
381 ///
382 /// See [`Float::log_base_float_base_prec_round`] for details and special cases.
383 ///
384 /// # Worst-case complexity
385 /// $T(n) = O(n (\log n)^2 \log\log n)$
386 ///
387 /// $M(n) = O(n (\log n)^2)$
388 ///
389 /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
390 ///
391 /// # Panics
392 /// Panics if `prec` is zero.
393 ///
394 /// # Examples
395 /// ```
396 /// use malachite_float::Float;
397 /// use std::cmp::Ordering::*;
398 ///
399 /// let (log, o) = (&Float::from(8)).log_base_float_base_prec_ref(&Float::from(4), 10);
400 /// assert_eq!(log.to_string(), "1.5000"); // log_4(8) = 3/2
401 /// assert_eq!(o, Equal);
402 /// ```
403 #[inline]
404 pub fn log_base_float_base_prec_ref(&self, base: &Self, prec: u64) -> (Self, Ordering) {
405 self.log_base_float_base_prec_round_ref(base, prec, Nearest)
406 }
407
408 /// Computes $\log_b x$, where $x$ and the base $b$ are both [`Float`]s, rounding the result to
409 /// the precision of the input and with the specified rounding mode. The [`Float`] is taken by
410 /// value and the base by reference. An [`Ordering`] is also returned.
411 ///
412 /// See [`Float::log_base_float_base_prec_round`] for details and special cases.
413 ///
414 /// # Worst-case complexity
415 /// $T(n) = O(n (\log n)^2 \log\log n)$
416 ///
417 /// $M(n) = O(n (\log n)^2)$
418 ///
419 /// where $T$ is time, $M$ is additional memory, and $n$ is the precision of the input.
420 ///
421 /// # Panics
422 /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input's
423 /// precision.
424 ///
425 /// # Examples
426 /// ```
427 /// use malachite_base::rounding_modes::RoundingMode::*;
428 /// use malachite_float::Float;
429 /// use std::cmp::Ordering::*;
430 ///
431 /// let (log, o) = Float::from(81).log_base_float_base_round(&Float::from(3), Exact);
432 /// assert_eq!(log.to_string(), "4.000"); // log_3(81) = 4
433 /// assert_eq!(o, Equal);
434 /// ```
435 #[inline]
436 pub fn log_base_float_base_round(self, base: &Self, rm: RoundingMode) -> (Self, Ordering) {
437 let prec = self.significant_bits();
438 self.log_base_float_base_prec_round(base, prec, rm)
439 }
440
441 /// Computes $\log_b x$, where $x$ and the base $b$ are both [`Float`]s, rounding the result to
442 /// the precision of the input and with the specified rounding mode. Both are taken by
443 /// reference. An [`Ordering`] is also returned.
444 ///
445 /// See [`Float::log_base_float_base_prec_round`] for details and special cases.
446 ///
447 /// # Worst-case complexity
448 /// $T(n) = O(n (\log n)^2 \log\log n)$
449 ///
450 /// $M(n) = O(n (\log n)^2)$
451 ///
452 /// where $T$ is time, $M$ is additional memory, and $n$ is the precision of the input.
453 ///
454 /// # Panics
455 /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input's
456 /// precision.
457 ///
458 /// # Examples
459 /// ```
460 /// use malachite_base::rounding_modes::RoundingMode::*;
461 /// use malachite_float::Float;
462 /// use std::cmp::Ordering::*;
463 ///
464 /// let (log, o) = (&Float::from(81)).log_base_float_base_round_ref(&Float::from(3), Exact);
465 /// assert_eq!(log.to_string(), "4.000"); // log_3(81) = 4
466 /// assert_eq!(o, Equal);
467 /// ```
468 #[inline]
469 pub fn log_base_float_base_round_ref(&self, base: &Self, rm: RoundingMode) -> (Self, Ordering) {
470 self.log_base_float_base_prec_round_ref(base, self.significant_bits(), rm)
471 }
472
473 /// Computes $\log_b x$, where $x$ and the base $b$ are both [`Float`]s, in place, rounding the
474 /// result to the specified precision and with the specified rounding mode. The base is taken by
475 /// reference. An [`Ordering`] is returned.
476 ///
477 /// See [`Float::log_base_float_base_prec_round`] for details and special cases.
478 ///
479 /// # Worst-case complexity
480 /// $T(n) = O(n (\log n)^2 \log\log n)$
481 ///
482 /// $M(n) = O(n (\log n)^2)$
483 ///
484 /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
485 ///
486 /// # Panics
487 /// Panics if `prec` is zero, or if `rm` is `Exact` but the result cannot be represented exactly
488 /// with the given precision.
489 ///
490 /// # Examples
491 /// ```
492 /// use malachite_base::rounding_modes::RoundingMode::*;
493 /// use malachite_float::Float;
494 /// use std::cmp::Ordering::*;
495 ///
496 /// let mut x = Float::from(8);
497 /// assert_eq!(
498 /// x.log_base_float_base_prec_round_assign(&Float::from(4), 10, Exact),
499 /// Equal
500 /// );
501 /// assert_eq!(x.to_string(), "1.5000"); // log_4(8) = 3/2
502 /// ```
503 #[inline]
504 pub fn log_base_float_base_prec_round_assign(
505 &mut self,
506 base: &Self,
507 prec: u64,
508 rm: RoundingMode,
509 ) -> Ordering {
510 let (result, o) = core::mem::take(self).log_base_float_base_prec_round(base, prec, rm);
511 *self = result;
512 o
513 }
514
515 /// Computes $\log_b x$, where $x$ and the base $b$ are both [`Float`]s, in place, rounding the
516 /// result to the nearest value of the specified precision. The base is taken by reference. An
517 /// [`Ordering`] is returned.
518 ///
519 /// See [`Float::log_base_float_base_prec_round`] for details and special cases.
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 `prec`.
527 ///
528 /// # Panics
529 /// Panics if `prec` is zero.
530 ///
531 /// # Examples
532 /// ```
533 /// use malachite_float::Float;
534 ///
535 /// let mut x = Float::from(8);
536 /// x.log_base_float_base_prec_assign(&Float::from(4), 10);
537 /// assert_eq!(x.to_string(), "1.5000"); // log_4(8) = 3/2
538 /// ```
539 #[inline]
540 pub fn log_base_float_base_prec_assign(&mut self, base: &Self, prec: u64) -> Ordering {
541 self.log_base_float_base_prec_round_assign(base, prec, Nearest)
542 }
543
544 /// Computes $\log_b x$, where $x$ and the base $b$ are both [`Float`]s, in place, rounding the
545 /// result to the precision of the input and with the specified rounding mode. The base is taken
546 /// by reference. An [`Ordering`] is returned.
547 ///
548 /// See [`Float::log_base_float_base_prec_round`] for details and special cases.
549 ///
550 /// # Worst-case complexity
551 /// $T(n) = O(n (\log n)^2 \log\log n)$
552 ///
553 /// $M(n) = O(n (\log n)^2)$
554 ///
555 /// where $T$ is time, $M$ is additional memory, and $n$ is the precision of the input.
556 ///
557 /// # Panics
558 /// Panics if `rm` is `Exact` but the result cannot be represented exactly with the input's
559 /// precision.
560 ///
561 /// # Examples
562 /// ```
563 /// use malachite_base::rounding_modes::RoundingMode::*;
564 /// use malachite_float::Float;
565 ///
566 /// let mut x = Float::from(81);
567 /// x.log_base_float_base_round_assign(&Float::from(3), Exact);
568 /// assert_eq!(x.to_string(), "4.000"); // log_3(81) = 4
569 /// ```
570 #[inline]
571 pub fn log_base_float_base_round_assign(&mut self, base: &Self, rm: RoundingMode) -> Ordering {
572 let prec = self.significant_bits();
573 self.log_base_float_base_prec_round_assign(base, prec, rm)
574 }
575}
576
577impl LogBase<Self> for Float {
578 type Output = Self;
579
580 /// Computes $\log_b x$, where $x$ and the base $b$ are both [`Float`]s, rounding the result to
581 /// the nearest value of the input's precision. Both are taken by value.
582 ///
583 /// See [`Float::log_base_float_base_prec_round`] for special cases.
584 ///
585 /// # Worst-case complexity
586 /// $T(n) = O(n (\log n)^2 \log\log n)$
587 ///
588 /// $M(n) = O(n (\log n)^2)$
589 ///
590 /// where $T$ is time, $M$ is additional memory, and $n$ is the precision of the input.
591 ///
592 /// # Examples
593 /// ```
594 /// use malachite_base::num::arithmetic::traits::LogBase;
595 /// use malachite_float::Float;
596 ///
597 /// assert_eq!(
598 /// Float::from(81).log_base(Float::from(3)).to_string(),
599 /// "4.000"
600 /// ); // log_3(81) = 4
601 /// assert_eq!(Float::from(9).log_base(Float::from(3)).to_string(), "2.00"); // log_3(9) = 2
602 /// ```
603 #[inline]
604 fn log_base(self, base: Self) -> Self {
605 let prec = self.significant_bits();
606 self.log_base_float_base_prec_round(&base, prec, Nearest).0
607 }
608}
609
610impl LogBase<&Float> for &Float {
611 type Output = Float;
612
613 /// Computes $\log_b x$, where $x$ and the base $b$ are both [`Float`]s, rounding the result to
614 /// the nearest value of the input's precision. Both are taken by reference.
615 ///
616 /// See [`Float::log_base_float_base_prec_round`] for special cases.
617 ///
618 /// # Worst-case complexity
619 /// $T(n) = O(n (\log n)^2 \log\log n)$
620 ///
621 /// $M(n) = O(n (\log n)^2)$
622 ///
623 /// where $T$ is time, $M$ is additional memory, and $n$ is the precision of the input.
624 ///
625 /// # Examples
626 /// ```
627 /// use malachite_base::num::arithmetic::traits::LogBase;
628 /// use malachite_float::Float;
629 ///
630 /// assert_eq!(
631 /// (&Float::from(81)).log_base(&Float::from(3)).to_string(),
632 /// "4.000"
633 /// ); // log_3(81)=4
634 /// assert_eq!(
635 /// (&Float::from(9)).log_base(&Float::from(3)).to_string(),
636 /// "2.00"
637 /// ); // log_3(9)=2
638 /// ```
639 #[inline]
640 fn log_base(self, base: &Float) -> Float {
641 self.log_base_float_base_prec_round_ref(base, self.significant_bits(), Nearest)
642 .0
643 }
644}
645
646impl LogBaseAssign<&Self> for Float {
647 /// Replaces a [`Float`] $x$ with $\log_b x$, where the base $b$ is a [`Float`], rounding the
648 /// result to the nearest value of the input's precision. The base is taken by reference.
649 ///
650 /// See [`Float::log_base_float_base_prec_round`] for special cases.
651 ///
652 /// # Worst-case complexity
653 /// $T(n) = O(n (\log n)^2 \log\log n)$
654 ///
655 /// $M(n) = O(n (\log n)^2)$
656 ///
657 /// where $T$ is time, $M$ is additional memory, and $n$ is the precision of the input.
658 ///
659 /// # Examples
660 /// ```
661 /// use malachite_base::num::arithmetic::traits::LogBaseAssign;
662 /// use malachite_float::Float;
663 ///
664 /// let mut x = Float::from(81);
665 /// x.log_base_assign(&Float::from(3));
666 /// assert_eq!(x.to_string(), "4.000"); // log_3(81) = 4
667 /// ```
668 #[inline]
669 fn log_base_assign(&mut self, base: &Self) {
670 let prec = self.significant_bits();
671 self.log_base_float_base_prec_round_assign(base, prec, Nearest);
672 }
673}
674
675/// Computes $\log_b x$, the base-$b$ logarithm of a primitive float, where the base $b$ is also a
676/// primitive float, returning a primitive float result. Using this function is more accurate than
677/// computing the logarithm using the standard library, whose logarithm functions are not always
678/// correctly rounded.
679///
680/// Unlike the integer- and rational-base logarithms, the base may be any primitive float: the
681/// function is defined as $\ln x / \ln b$ and never panics on an input value. A base in $(0,1)$
682/// gives a (sign-flipped) logarithm, and the non-normal and degenerate bases follow the limits
683/// below.
684///
685/// $$
686/// f(x,b) = \log_b x+\varepsilon.
687/// $$
688/// - If $\log_b x$ is infinite, zero, or `NaN`, $\varepsilon$ may be ignored or assumed to be 0.
689/// - If $\log_b x$ is finite and nonzero, then $|\varepsilon| < 2^{\lfloor\log_2 |\log_b
690/// x|\rfloor-p}$, where $p$ is precision of the output (typically 24 if `T` is a [`f32`] and 53
691/// if `T` is a [`f64`], but less if the output is subnormal).
692///
693/// Special cases (with $b$ the base):
694/// - $f(\text{NaN},b)=\text{NaN}$, and $f(x,\text{NaN})=\text{NaN}$
695/// - $f(x,b)=\text{NaN}$ for $x<0$ or $b<0$
696/// - $f(\infty,b)=\infty$ for $b>1$, and $-\infty$ for $0\leq b<1$
697/// - $f(\pm0.0,b)=-\infty$ for $b>1$, and $\infty$ for $0<b<1$
698/// - $f(1.0,b)=0.0$ (with the sign of $1/\ln b$)
699/// - $f(x,\infty)=0.0$ for finite $x>0$ (and $\text{NaN}$ for $x\in\{\pm\infty,\pm0.0\}$)
700/// - $f(x,\pm0.0)=0.0$ for finite $x>0$ (and $\text{NaN}$ for $x\in\{\pm\infty,\pm0.0\}$)
701/// - $f(x,1.0)=\infty$ for $x>1$ or $x=\infty$, $-\infty$ for $0\leq x<1$, and $\text{NaN}$ for
702/// $x=1$
703///
704/// This function can both overflow (for a base near 1) and underflow (for an $x$ near 1).
705///
706/// # Worst-case complexity
707/// Constant time and additional memory.
708///
709/// # Examples
710/// ```
711/// use malachite_base::num::float::NiceFloat;
712/// use malachite_float::float::arithmetic::log_base_float_base::*;
713///
714/// // log_4(8) = 3/2
715/// assert_eq!(
716/// NiceFloat(primitive_float_log_base_float_base(8.0f32, 4.0)),
717/// NiceFloat(1.5)
718/// );
719/// // log_(1/2)(4) = -2
720/// assert_eq!(
721/// NiceFloat(primitive_float_log_base_float_base(4.0f32, 0.5)),
722/// NiceFloat(-2.0)
723/// );
724/// // log_10(50)
725/// assert_eq!(
726/// NiceFloat(primitive_float_log_base_float_base(50.0f32, 10.0)),
727/// NiceFloat(1.69897)
728/// );
729/// // log_inf(8) = 0
730/// assert_eq!(
731/// NiceFloat(primitive_float_log_base_float_base(8.0f32, f32::INFINITY)),
732/// NiceFloat(0.0)
733/// );
734/// assert!(primitive_float_log_base_float_base(-1.0f32, 10.0).is_nan());
735/// assert!(primitive_float_log_base_float_base(8.0f32, f32::NAN).is_nan());
736/// ```
737#[inline]
738#[allow(clippy::type_repetition_in_bounds)]
739pub fn primitive_float_log_base_float_base<T: PrimitiveFloat>(x: T, base: T) -> T
740where
741 Float: From<T> + PartialOrd<T>,
742 for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
743{
744 emulate_float_float_to_float_fn(
745 |x, base, prec| x.log_base_float_base_prec(&base, prec),
746 x,
747 base,
748 )
749}