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}