Skip to main content

malachite_float/constants/
pi_over_3.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 $\pi/3$, with the given precision and rounded using the given
24    /// [`RoundingMode`]. An [`Ordering`] is also returned, indicating whether the rounded value is
25    /// less than or greater than the exact value of the constant. (Since the constant is
26    /// irrational, the rounded value is never equal to the exact value.)
27    ///
28    /// $$
29    /// x = \pi/3+\varepsilon.
30    /// $$
31    /// - If $m$ is not `Nearest`, then $|\varepsilon| < 2^{-p+1}$.
32    /// - If $m$ is `Nearest`, then $|\varepsilon| < 2^{-p}$.
33    ///
34    /// The constant is irrational and transcendental.
35    ///
36    /// The output has precision `prec`.
37    ///
38    /// # Worst-case complexity
39    /// $T(n) = O(n (\log n)^2 \log\log n)$
40    ///
41    /// $M(n) = O(n (\log n)^2)$
42    ///
43    /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
44    ///
45    /// # Panics
46    /// Panics if `prec` is zero or if `rm` is `Exact`.
47    ///
48    /// # Examples
49    /// ```
50    /// use malachite_base::rounding_modes::RoundingMode::*;
51    /// use malachite_float::Float;
52    /// use std::cmp::Ordering::*;
53    ///
54    /// let (pi_over_3, o) = Float::pi_over_3_prec_round(100, Floor);
55    /// assert_eq!(pi_over_3.to_string(), "1.047197551196597746154214461092");
56    /// assert_eq!(o, Less);
57    ///
58    /// let (pi_over_3, o) = Float::pi_over_3_prec_round(100, Ceiling);
59    /// assert_eq!(pi_over_3.to_string(), "1.047197551196597746154214461094");
60    /// assert_eq!(o, Greater);
61    /// ```
62    pub fn pi_over_3_prec_round(prec: u64, rm: RoundingMode) -> (Self, Ordering) {
63        const THREE: Float = Float::const_from_unsigned(3);
64        let mut working_prec = prec + 10;
65        let mut increment = Limb::WIDTH;
66        loop {
67            let pi_over_3 = Self::pi_prec(working_prec).0 / THREE;
68            if float_can_round(
69                pi_over_3.significand_ref().unwrap(),
70                working_prec - 1,
71                prec,
72                rm,
73            ) {
74                return Self::from_float_prec_round(pi_over_3, prec, rm);
75            }
76            working_prec += increment;
77            increment = working_prec >> 1;
78        }
79    }
80
81    /// Returns an approximation of $\pi/3$, with the given precision and rounded to the nearest
82    /// [`Float`] of that precision. An [`Ordering`] is also returned, indicating whether the
83    /// rounded value is less than or greater than the exact value of the constant. (Since the
84    /// constant is irrational, the rounded value is never equal to the exact value.)
85    ///
86    /// $$
87    /// x = \pi/3+\varepsilon.
88    /// $$
89    /// - $|\varepsilon| < 2^{-p}$.
90    ///
91    /// The constant is irrational and transcendental.
92    ///
93    /// The output has precision `prec`.
94    ///
95    /// # Worst-case complexity
96    /// $T(n) = O(n (\log n)^2 \log\log n)$
97    ///
98    /// $M(n) = O(n (\log n)^2)$
99    ///
100    /// where $T$ is time, $M$ is additional memory, and $n$ is `prec`.
101    ///
102    /// # Panics
103    /// Panics if `prec` is zero.
104    ///
105    /// # Examples
106    /// ```
107    /// use malachite_float::Float;
108    /// use std::cmp::Ordering::*;
109    ///
110    /// let (pi_over_3, o) = Float::pi_over_3_prec(1);
111    /// assert_eq!(pi_over_3.to_string(), "1.0");
112    /// assert_eq!(o, Less);
113    ///
114    /// let (pi_over_3, o) = Float::pi_over_3_prec(10);
115    /// assert_eq!(pi_over_3.to_string(), "1.047");
116    /// assert_eq!(o, Less);
117    ///
118    /// let (pi_over_3, o) = Float::pi_over_3_prec(100);
119    /// assert_eq!(pi_over_3.to_string(), "1.047197551196597746154214461094");
120    /// assert_eq!(o, Greater);
121    /// ```
122    #[inline]
123    pub fn pi_over_3_prec(prec: u64) -> (Self, Ordering) {
124        Self::pi_over_3_prec_round(prec, Nearest)
125    }
126}