malachite_float/constants/
prime_constant.rs

1// Copyright © 2025 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;
10use core::cmp::Ordering;
11use malachite_base::num::factorization::primes::prime_indicator_sequence_less_than_or_equal_to;
12use malachite_base::rounding_modes::RoundingMode::{self, *};
13
14impl Float {
15    /// Returns an approximation to the prime constant, with the given precision and rounded using
16    /// the given [`RoundingMode`]. An [`Ordering`] is also returned, indicating whether the rounded
17    /// value is less than or greater than the exact value of the constant. (Since the constant is
18    /// irrational, the rounded value is never equal to the exact value.)
19    ///
20    /// The prime constant is the real number whose $n$th bit is prime if and only if $n$ is prime.
21    /// That is,
22    /// $$
23    /// P = \sum_{p\ \text{prime}\}2^{-p}.
24    /// $$
25    ///
26    /// The constant is irrational. It is unknown whether it is transcendental; see
27    /// <https://mathoverflow.net/questions/114905>.
28    ///
29    /// The output has precision `prec`.
30    ///
31    /// # Worst-case complexity
32    /// $T(n) = O(n)$
33    ///
34    /// $M(n) = O(n)$
35    ///
36    /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
37    ///
38    /// # Panics
39    /// Panics if `prec` is zero or if `rm` is `Exact`.
40    ///
41    /// # Examples
42    /// ```
43    /// use malachite_base::rounding_modes::RoundingMode::*;
44    /// use malachite_float::Float;
45    /// use std::cmp::Ordering::*;
46    ///
47    /// let (pc, o) = Float::prime_constant_prec_round(100, Floor);
48    /// assert_eq!(pc.to_string(), "0.4146825098511116602481096221542");
49    /// assert_eq!(o, Less);
50    ///
51    /// let (pc, o) = Float::prime_constant_prec_round(100, Ceiling);
52    /// assert_eq!(pc.to_string(), "0.4146825098511116602481096221546");
53    /// assert_eq!(o, Greater);
54    /// ```
55    pub fn prime_constant_prec_round(prec: u64, rm: RoundingMode) -> (Self, Ordering) {
56        // Strictly speaking, this call violates the preconditions for
57        // `non_dyadic_from_bits_prec_round`, because the iterator passed in is finite. But since we
58        // know exactly how many bits `non_dyadic_from_bits_prec_round` will read, we can get away
59        // with this.
60        Self::non_dyadic_from_bits_prec_round(
61            prime_indicator_sequence_less_than_or_equal_to(if rm == Nearest {
62                prec + 2
63            } else {
64                prec + 1
65            }),
66            prec,
67            rm,
68        )
69    }
70
71    /// Returns an approximation to the prime constant, with the given precision and rounded to the
72    /// nearest [`Float`] of that precision. An [`Ordering`] is also returned, indicating whether
73    /// the rounded value is less than or greater than the exact value of the constant. (Since the
74    /// constant is irrational, the rounded value is never equal to the exact value.)
75    ///
76    /// The prime constant is the real number whose $n$th bit is prime if and only if $n$ is prime.
77    /// That is,
78    /// $$
79    /// P = \sum_{p\ \text{prime}\}2^{-p}.
80    /// $$
81    ///
82    /// The constant is irrational. It is unknown whether it is transcendental; see
83    /// <https://mathoverflow.net/questions/114905>.
84    ///
85    /// The output has precision `prec`.
86    ///
87    /// # Worst-case complexity
88    /// $T(n) = O(n)$
89    ///
90    /// $M(n) = O(n)$
91    ///
92    /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
93    ///
94    /// # Panics
95    /// Panics if `prec` is zero.
96    ///
97    /// # Examples
98    /// ```
99    /// use malachite_float::Float;
100    /// use std::cmp::Ordering::*;
101    ///
102    /// let (pc, o) = Float::prime_constant_prec(1);
103    /// assert_eq!(pc.to_string(), "0.5");
104    /// assert_eq!(o, Greater);
105    ///
106    /// let (pc, o) = Float::prime_constant_prec(10);
107    /// assert_eq!(pc.to_string(), "0.4146");
108    /// assert_eq!(o, Less);
109    ///
110    /// let (pc, o) = Float::prime_constant_prec(100);
111    /// assert_eq!(pc.to_string(), "0.4146825098511116602481096221542");
112    /// assert_eq!(o, Less);
113    /// ```
114    #[inline]
115    pub fn prime_constant_prec(prec: u64) -> (Self, Ordering) {
116        Self::prime_constant_prec_round(prec, Nearest)
117    }
118}