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