Skip to main content

malachite_float/float/constants/
gelfond_schneider_constant.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::{Float, floor_and_ceiling};
10use core::cmp::Ordering::{self, *};
11use malachite_base::num::basic::integers::PrimitiveInt;
12use malachite_base::rounding_modes::RoundingMode::{self, *};
13use malachite_nz::platform::Limb;
14
15impl Float {
16    /// Returns an approximation of the Gelfond–Schneider constant, $2^{\sqrt 2}$, with the given
17    /// precision and rounded using the given [`RoundingMode`]. An [`Ordering`] is also returned,
18    /// indicating whether the rounded value is less than or greater than the exact value of the
19    /// constant. (Since the constant is irrational, the rounded value is never equal to the exact
20    /// value.)
21    ///
22    /// $$
23    /// x = 2^{\sqrt 2}+\varepsilon.
24    /// $$
25    /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{-p+2}$.
26    /// - If $m$ is `Nearest`, then $|\varepsilon| < 2^{-p+1}$.
27    ///
28    /// The constant is irrational and transcendental.
29    ///
30    /// The output has precision `prec`.
31    ///
32    /// # Worst-case complexity
33    /// $T(n) = O(n^{3/2} \log n \log\log n)$
34    ///
35    /// $M(n) = O(n \log n)$
36    ///
37    /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
38    ///
39    /// # Panics
40    /// Panics if `prec` is zero or if `rm` is `Exact`.
41    ///
42    /// # Examples
43    /// ```
44    /// use malachite_base::rounding_modes::RoundingMode::*;
45    /// use malachite_float::Float;
46    /// use std::cmp::Ordering::*;
47    ///
48    /// let (gelfond_schneider_constant, o) =
49    ///     Float::gelfond_schneider_constant_prec_round(100, Floor);
50    /// assert_eq!(
51    ///     gelfond_schneider_constant.to_string(),
52    ///     "2.6651441426902251886502972498731"
53    /// );
54    /// assert_eq!(o, Less);
55    ///
56    /// let (gelfond_schneider_constant, o) =
57    ///     Float::gelfond_schneider_constant_prec_round(100, Ceiling);
58    /// assert_eq!(
59    ///     gelfond_schneider_constant.to_string(),
60    ///     "2.6651441426902251886502972498762"
61    /// );
62    /// assert_eq!(o, Greater);
63    /// ```
64    pub fn gelfond_schneider_constant_prec_round(prec: u64, rm: RoundingMode) -> (Self, Ordering) {
65        let mut working_prec = prec + 10;
66        let mut increment = Limb::WIDTH;
67        loop {
68            let (sqrt_2_lo, sqrt_2_hi) =
69                floor_and_ceiling(Self::sqrt_2_prec_round(working_prec, Floor));
70            // 2^x is increasing, so 2^sqrt_2_lo <= 2^sqrt(2) <= 2^sqrt_2_hi.
71            let (gelfond_schneider_constant_lo, mut o_lo) = Self::from_float_prec_round(
72                Self::power_of_2_of_float_round(sqrt_2_lo, Floor).0,
73                prec,
74                rm,
75            );
76            let (gelfond_schneider_constant_hi, mut o_hi) = Self::from_float_prec_round(
77                Self::power_of_2_of_float_round(sqrt_2_hi, Ceiling).0,
78                prec,
79                rm,
80            );
81            if o_lo == Equal {
82                o_lo = o_hi;
83            }
84            if o_hi == Equal {
85                o_hi = o_lo;
86            }
87            if o_lo == o_hi && gelfond_schneider_constant_lo == gelfond_schneider_constant_hi {
88                return (gelfond_schneider_constant_lo, o_lo);
89            }
90            working_prec += increment;
91            increment = working_prec >> 1;
92        }
93    }
94
95    /// Returns an approximation of the Gelfond–Schneider constant, $2^{\sqrt 2}$, with the given
96    /// precision and rounded to the nearest [`Float`] of that precision. An [`Ordering`] is also
97    /// returned, indicating whether the rounded value is less than or greater than the exact value
98    /// of the constant. (Since the constant is irrational, the rounded value is never equal to the
99    /// exact value.)
100    ///
101    /// $$
102    /// x = 2^{\sqrt 2}+\varepsilon.
103    /// $$
104    /// - $|\varepsilon| < 2^{-p+1}$.
105    ///
106    /// The constant is irrational and transcendental.
107    ///
108    /// The output has precision `prec`.
109    ///
110    /// # Worst-case complexity
111    /// $T(n) = O(n^{3/2} \log n \log\log n)$
112    ///
113    /// $M(n) = O(n \log n)$
114    ///
115    /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
116    ///
117    /// # Panics
118    /// Panics if `prec` is zero.
119    ///
120    /// # Examples
121    /// ```
122    /// use malachite_float::Float;
123    /// use std::cmp::Ordering::*;
124    ///
125    /// let (gelfond_schneider_constant, o) = Float::gelfond_schneider_constant_prec(1);
126    /// assert_eq!(gelfond_schneider_constant.to_string(), "2.0");
127    /// assert_eq!(o, Less);
128    ///
129    /// let (gelfond_schneider_constant, o) = Float::gelfond_schneider_constant_prec(10);
130    /// assert_eq!(gelfond_schneider_constant.to_string(), "2.6641");
131    /// assert_eq!(o, Less);
132    ///
133    /// let (gelfond_schneider_constant, o) = Float::gelfond_schneider_constant_prec(100);
134    /// assert_eq!(
135    ///     gelfond_schneider_constant.to_string(),
136    ///     "2.6651441426902251886502972498731"
137    /// );
138    /// assert_eq!(o, Less);
139    /// ```
140    #[inline]
141    pub fn gelfond_schneider_constant_prec(prec: u64) -> (Self, Ordering) {
142        Self::gelfond_schneider_constant_prec_round(prec, Nearest)
143    }
144}