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}