malachite_float/float/constants/copeland_erdos_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, emulate_constant_to_float_fn};
10use core::cmp::Ordering;
11use malachite_base::num::basic::floats::PrimitiveFloat;
12use malachite_base::num::conversion::traits::{Digits, ExactFrom, RoundingFrom};
13use malachite_base::num::factorization::traits::Primes;
14use malachite_base::rounding_modes::RoundingMode::{self, Nearest};
15
16// The digits of the Copeland–Erdős constant in the given base: the base-`base` representations
17// of the primes run together.
18fn copeland_erdos_digits(base: u64) -> impl Iterator<Item = u64> {
19 u64::primes().flat_map(move |p| p.to_digits_desc(&base))
20}
21
22impl Float {
23 /// Returns an approximation of the Copeland–Erdős constant in a given base, with the given
24 /// precision and rounded using the given [`RoundingMode`]. An [`Ordering`] is also returned,
25 /// indicating whether the rounded value is less than or greater than the exact value of the
26 /// constant. (Since the constant is irrational, the rounded value is never equal to the exact
27 /// value.)
28 ///
29 /// The Copeland–Erdős constant in base $b$ is formed by concatenating the base-$b$
30 /// representations of the primes after the point:
31 /// $$
32 /// CE_b = 0.\overline{p_1 p_2 p_3 \ldots}_b+\varepsilon,
33 /// $$
34 /// where $p_i$ is the $i$th prime written in base $b$.
35 /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{\lfloor\log_2 CE_b\rfloor-p+1}$.
36 /// - If $m$ is `Nearest`, then $|\varepsilon| < 2^{\lfloor\log_2 CE_b\rfloor-p}$.
37 ///
38 /// Base 10 gives the classical constant, $0.235711131719\ldots$. The Copeland–Erdős theorem
39 /// says that it is normal in its base, which in particular makes it irrational.
40 ///
41 /// The output has precision `prec`.
42 ///
43 /// # Worst-case complexity
44 /// $T(n) = O(n (\log n)^2 \log\log n)$
45 ///
46 /// $M(n) = O(n \log n)$
47 ///
48 /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
49 ///
50 /// # Panics
51 /// Panics if `base` is less than 2, if `prec` is zero, or if `rm` is `Exact`.
52 ///
53 /// # Examples
54 /// ```
55 /// use malachite_base::rounding_modes::RoundingMode::*;
56 /// use malachite_float::Float;
57 /// use std::cmp::Ordering::*;
58 ///
59 /// // In base 16 the digits are the primes in hexadecimal: 2, 3, 5, 7, b, d, 11, 13, 17,
60 /// // ..., which the hexadecimal representation spells out.
61 /// let (x, o) = Float::copeland_erdos_constant_base_prec_round(16, 100, Floor);
62 /// assert_eq!(x.to_string(), "0.13805753390178350683643564212329");
63 /// assert_eq!(format!("{x:#x}"), "0x0.2357bd1113171d1f25292b2f34");
64 /// assert_eq!(o, Less);
65 ///
66 /// let (x, o) = Float::copeland_erdos_constant_base_prec_round(16, 100, Ceiling);
67 /// assert_eq!(x.to_string(), "0.13805753390178350683643564212348");
68 /// assert_eq!(format!("{x:#x}"), "0x0.2357bd1113171d1f25292b2f38");
69 /// assert_eq!(o, Greater);
70 /// ```
71 #[inline]
72 pub fn copeland_erdos_constant_base_prec_round(
73 base: u64,
74 prec: u64,
75 rm: RoundingMode,
76 ) -> (Self, Ordering) {
77 Self::non_dyadic_from_digits_prec_round(copeland_erdos_digits(base), base, prec, rm)
78 }
79
80 /// Returns an approximation of the Copeland–Erdős constant in a given base, with the given
81 /// precision and rounded to the nearest [`Float`] of that precision. An [`Ordering`] is also
82 /// returned, indicating whether the rounded value is less than or greater than the exact value.
83 ///
84 /// See
85 /// [`copeland_erdos_constant_base_prec_round`](Float::copeland_erdos_constant_base_prec_round)
86 /// for details.
87 ///
88 /// # Worst-case complexity
89 /// $T(n) = O(n (\log n)^2 \log\log n)$
90 ///
91 /// $M(n) = O(n \log n)$
92 ///
93 /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
94 ///
95 /// # Panics
96 /// Panics if `base` is less than 2 or if `prec` is zero.
97 ///
98 /// # Examples
99 /// ```
100 /// use malachite_float::Float;
101 /// use std::cmp::Ordering::*;
102 ///
103 /// // In base 16 the digits are the primes in hexadecimal: 2, 3, 5, 7, b, d, 11, 13, ...
104 /// let (x, o) = Float::copeland_erdos_constant_base_prec(16, 100);
105 /// assert_eq!(x.to_string(), "0.13805753390178350683643564212329");
106 /// assert_eq!(format!("{x:#x}"), "0x0.2357bd1113171d1f25292b2f34");
107 /// assert_eq!(o, Less);
108 ///
109 /// // Base 3 concatenates 2, 12, 21, 111, 122, 200, ...
110 /// let (x, o) = Float::copeland_erdos_constant_base_prec(3, 50);
111 /// assert_eq!(x.to_string(), "0.80174949296954523");
112 /// assert_eq!(o, Greater);
113 /// ```
114 #[inline]
115 pub fn copeland_erdos_constant_base_prec(base: u64, prec: u64) -> (Self, Ordering) {
116 Self::copeland_erdos_constant_base_prec_round(base, prec, Nearest)
117 }
118
119 /// Returns an approximation of the Copeland–Erdős constant in base 10, with the given
120 /// precision and rounded using the given [`RoundingMode`]. An [`Ordering`] is also returned,
121 /// indicating whether the rounded value is less than or greater than the exact value of the
122 /// constant. (Since the constant is irrational, the rounded value is never equal to the exact
123 /// value.)
124 ///
125 /// The Copeland–Erdős constant is formed by concatenating the decimal representations of the
126 /// primes after the radix point.
127 ///
128 /// $$
129 /// x = CE = 0.235711131719\ldots+\varepsilon.
130 /// $$
131 /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{-p}$.
132 /// - If $m$ is `Nearest`, then $|\varepsilon| < 2^{-p-1}$.
133 ///
134 /// The constant is irrational and transcendental.
135 ///
136 /// The output has precision `prec`.
137 ///
138 /// This is the base-10 specialization of
139 /// [`copeland_erdos_constant_base_prec_round`](Float::copeland_erdos_constant_base_prec_round).
140 ///
141 /// # Worst-case complexity
142 /// $T(n) = O(n \log n \log\log n)$
143 ///
144 /// $M(n) = O(n \log n)$
145 ///
146 /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
147 ///
148 /// # Panics
149 /// Panics if `prec` is zero or if `rm` is `Exact`.
150 ///
151 /// # Examples
152 /// ```
153 /// use malachite_base::rounding_modes::RoundingMode::*;
154 /// use malachite_float::Float;
155 /// use std::cmp::Ordering::*;
156 ///
157 /// let (x, o) = Float::copeland_erdos_constant_prec_round(100, Floor);
158 /// assert_eq!(x.to_string(), "0.23571113171923293137414347535946");
159 /// assert_eq!(o, Less);
160 ///
161 /// let (x, o) = Float::copeland_erdos_constant_prec_round(100, Ceiling);
162 /// assert_eq!(x.to_string(), "0.23571113171923293137414347535966");
163 /// assert_eq!(o, Greater);
164 /// ```
165 #[inline]
166 pub fn copeland_erdos_constant_prec_round(prec: u64, rm: RoundingMode) -> (Self, Ordering) {
167 Self::copeland_erdos_constant_base_prec_round(10, prec, rm)
168 }
169
170 /// Returns an approximation of the Copeland–Erdős constant in base 10, with the given
171 /// precision and rounded to the nearest [`Float`] of that precision. An [`Ordering`] is also
172 /// returned, indicating whether the rounded value is less than or greater than the exact value
173 /// of the constant. (Since the constant is irrational, the rounded value is never equal to the
174 /// exact value.)
175 ///
176 /// The Copeland–Erdős constant is formed by concatenating the decimal representations of the
177 /// primes after the radix point.
178 ///
179 /// $$
180 /// x = CE = 0.235711131719\ldots+\varepsilon.
181 /// $$
182 /// - $|\varepsilon| < 2^{-p-1}$.
183 ///
184 /// The constant is irrational and transcendental.
185 ///
186 /// The output has precision `prec`.
187 ///
188 /// This is the base-10 specialization of
189 /// [`copeland_erdos_constant_base_prec`](Float::copeland_erdos_constant_base_prec).
190 ///
191 /// # Worst-case complexity
192 /// $T(n) = O(n \log n \log\log n)$
193 ///
194 /// $M(n) = O(n \log n)$
195 ///
196 /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
197 ///
198 /// # Panics
199 /// Panics if `prec` is zero.
200 ///
201 /// # Examples
202 /// ```
203 /// use malachite_float::Float;
204 ///
205 /// let x = Float::copeland_erdos_constant_prec(100).0;
206 /// assert_eq!(x.to_string(), "0.23571113171923293137414347535966");
207 /// ```
208 #[inline]
209 pub fn copeland_erdos_constant_prec(prec: u64) -> (Self, Ordering) {
210 Self::copeland_erdos_constant_base_prec(10, prec)
211 }
212}
213
214/// Computes an approximation of the Copeland–Erdős constant in a given base, returning a
215/// primitive float.
216///
217/// The Copeland–Erdős constant in base $b$ is formed by concatenating the base-$b$
218/// representations of the primes after the radix point.
219///
220/// $$
221/// CE_b = 0.\overline{2\,3\,5\,7\,11\,\ldots}_b.
222/// $$
223///
224/// The returned value is the one closest to the true constant; ties are broken by the
225/// round-half-to-even rule. Computing the constant this way is more accurate than summing its
226/// digits in primitive-float arithmetic, where each addition rounds.
227///
228/// $$
229/// f(b) = CE_b+\varepsilon,
230/// $$
231/// where $|\varepsilon| < 2^{\lfloor\log_2 |CE_b|\rfloor-p}$ and $p$ is the precision of the output
232/// (24 if `T` is a [`f32`] and 53 if `T` is a [`f64`]).
233///
234/// The constant lies in $[1/b,1)$, and $b$ is at most $2^{64}-1$, so this function can neither
235/// overflow nor underflow.
236///
237/// # Worst-case complexity
238/// Constant time and additional memory.
239///
240/// # Panics
241/// Panics if `base` is less than 2.
242///
243/// # Examples
244/// ```
245/// use malachite_base::num::float::NiceFloat;
246/// use malachite_float::float::constants::copeland_erdos_constant::*;
247///
248/// // The classical constant, 0.23571113171923...
249/// assert_eq!(
250/// NiceFloat(primitive_float_copeland_erdos_constant_base::<f32>(10)),
251/// NiceFloat(0.23571113)
252/// );
253/// assert_eq!(
254/// NiceFloat(primitive_float_copeland_erdos_constant_base::<f64>(10)),
255/// NiceFloat(0.23571113171923294)
256/// );
257/// // Base 1000 gives each prime its own three-digit block: 002, 003, 005, 007, 011, 013
258/// assert_eq!(
259/// NiceFloat(primitive_float_copeland_erdos_constant_base::<f64>(1000)),
260/// NiceFloat(0.002003005007011013)
261/// );
262/// ```
263#[inline]
264#[allow(clippy::type_repetition_in_bounds)]
265pub fn primitive_float_copeland_erdos_constant_base<T: PrimitiveFloat>(base: u64) -> T
266where
267 Float: PartialOrd<T>,
268 for<'a> T: ExactFrom<&'a Float> + RoundingFrom<&'a Float>,
269{
270 emulate_constant_to_float_fn(|prec| Float::copeland_erdos_constant_base_prec(base, prec))
271}