Skip to main content

malachite_float/constants/
lemniscate_constant.rs

1// Copyright © 2026 Mikhail Hogrefe
2//
3// Uses code adopted from the GNU MPFR Library.
4//
5//      Copyright 1999, 2001-2024 Free Software Foundation, Inc.
6//
7//      Contributed by the AriC and Caramba projects, INRIA.
8//
9// This file is part of Malachite.
10//
11// Malachite is free software: you can redistribute it and/or modify it under the terms of the GNU
12// Lesser General Public License (LGPL) as published by the Free Software Foundation; either version
13// 3 of the License, or (at your option) any later version. See <https://www.gnu.org/licenses/>.
14
15use crate::Float;
16use core::cmp::Ordering;
17use malachite_base::num::basic::integers::PrimitiveInt;
18use malachite_base::rounding_modes::RoundingMode::{self, *};
19use malachite_nz::natural::arithmetic::float_extras::float_can_round;
20use malachite_nz::platform::Limb;
21
22impl Float {
23    /// Returns an approximation of the lemniscate constant $\varpi$, with the given precision and
24    /// rounded using the given [`RoundingMode`]. An [`Ordering`] is also returned, indicating
25    /// whether the rounded value is less than or greater than the exact value of the constant.
26    /// (Since the constant is irrational, the rounded value is never equal to the exact value.)
27    ///
28    /// $$
29    /// x = \varpi+\varepsilon=\pi G+\varepsilon,
30    /// $$
31    /// where $G$ is Gauss's constant.
32    /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{-p+2}$.
33    /// - If $m$ is `Nearest`, then $|\varepsilon| < 2^{-p+1}$.
34    ///
35    /// The constant is irrational and transcendental.
36    ///
37    /// The output has precision `prec`.
38    ///
39    /// # Worst-case complexity
40    /// $T(n) = O(n (\log n)^2 \log\log n)$
41    ///
42    /// $M(n) = O(n (\log n)^2)$
43    ///
44    /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
45    ///
46    /// # Panics
47    /// Panics if `prec` is zero or if `rm` is `Exact`.
48    ///
49    /// # Examples
50    /// ```
51    /// use malachite_base::rounding_modes::RoundingMode::*;
52    /// use malachite_float::Float;
53    /// use std::cmp::Ordering::*;
54    ///
55    /// let (lemniscate_constant, o) = Float::lemniscate_constant_prec_round(100, Floor);
56    /// assert_eq!(
57    ///     lemniscate_constant.to_string(),
58    ///     "2.62205755429211981046483958989"
59    /// );
60    /// assert_eq!(o, Less);
61    ///
62    /// let (lemniscate_constant, o) = Float::lemniscate_constant_prec_round(100, Ceiling);
63    /// assert_eq!(
64    ///     lemniscate_constant.to_string(),
65    ///     "2.622057554292119810464839589893"
66    /// );
67    /// assert_eq!(o, Greater);
68    /// ```
69    pub fn lemniscate_constant_prec_round(prec: u64, rm: RoundingMode) -> (Self, Ordering) {
70        let mut working_prec = prec + 10;
71        let mut increment = Limb::WIDTH;
72        loop {
73            let lemniscate_constant =
74                Self::pi_prec(working_prec).0 * Self::gauss_constant_prec(working_prec).0;
75            if float_can_round(
76                lemniscate_constant.significand_ref().unwrap(),
77                working_prec - 2,
78                prec,
79                rm,
80            ) {
81                return Self::from_float_prec_round(lemniscate_constant, prec, rm);
82            }
83            working_prec += increment;
84            increment = working_prec >> 1;
85        }
86    }
87
88    /// Returns an approximation of the lemniscate constant $\varpi$, with the given precision and
89    /// rounded to the nearest [`Float`] of that precision. An [`Ordering`] is also returned,
90    /// indicating whether the rounded value is less than or greater than the exact value of the
91    /// constant. (Since the constant is irrational, the rounded value is never equal to the exact
92    /// value.)
93    ///
94    /// $$
95    /// x = \varpi+\varepsilon=\pi G+\varepsilon,
96    /// $$
97    /// where $G$ is Gauss's constant.
98    /// - $|\varepsilon| < 2^{-p+1}$.
99    ///
100    /// The constant is irrational and transcendental.
101    ///
102    /// The output has precision `prec`.
103    ///
104    /// # Worst-case complexity
105    /// $T(n) = O(n (\log n)^2 \log\log n)$
106    ///
107    /// $M(n) = O(n (\log n)^2)$
108    ///
109    /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
110    ///
111    /// # Panics
112    /// Panics if `prec` is zero.
113    ///
114    /// # Examples
115    /// ```
116    /// use malachite_float::Float;
117    /// use std::cmp::Ordering::*;
118    ///
119    /// let (lemniscate_constant, o) = Float::lemniscate_constant_prec(1);
120    /// assert_eq!(lemniscate_constant.to_string(), "2.0");
121    /// assert_eq!(o, Less);
122    ///
123    /// let (lemniscate_constant, o) = Float::lemniscate_constant_prec(10);
124    /// assert_eq!(lemniscate_constant.to_string(), "2.621");
125    /// assert_eq!(o, Less);
126    ///
127    /// let (lemniscate_constant, o) = Float::lemniscate_constant_prec(100);
128    /// assert_eq!(
129    ///     lemniscate_constant.to_string(),
130    ///     "2.62205755429211981046483958989"
131    /// );
132    /// assert_eq!(o, Less);
133    /// ```
134    #[inline]
135    pub fn lemniscate_constant_prec(prec: u64) -> (Self, Ordering) {
136        Self::lemniscate_constant_prec_round(prec, Nearest)
137    }
138}