astro_float_num/ops/consts/mod.rs
1mod e;
2mod ln10;
3mod ln2;
4mod pi;
5
6use crate::common::buf::WordBuf;
7use crate::common::util::round_p;
8use crate::mantissa::Mantissa;
9use crate::num::BigFloatNumber;
10use crate::ops::consts::e::ECache;
11use crate::ops::consts::ln10::Ln10Cache;
12use crate::ops::consts::ln2::Ln2Cache;
13use crate::ops::consts::pi::PiCache;
14use crate::BigFloat;
15use crate::Error;
16use crate::RoundingMode;
17
18#[cfg(not(feature = "std"))]
19use alloc::vec::Vec;
20
21/// Constants cache contains arbitrary-precision mathematical constants.
22#[derive(Debug)]
23pub struct Consts {
24 pi: PiCache,
25 e: ECache,
26 ln2: Ln2Cache,
27 ln10: Ln10Cache,
28 tenpowers: Vec<(WordBuf, WordBuf, usize)>,
29}
30
31/// In an ideal situation, the `Consts` structure is initialized with `Consts::new` only once,
32/// and then used where needed.
33impl Consts {
34 /// Initializes the constants cache.
35 ///
36 /// ## Errors
37 ///
38 /// - MemoryAllocation: failed to allocate memory for mantissa.
39 pub fn new() -> Result<Self, Error> {
40 Ok(Consts {
41 pi: PiCache::new()?,
42 e: ECache::new()?,
43 ln2: Ln2Cache::new()?,
44 ln10: Ln10Cache::new()?,
45 tenpowers: Vec::new(),
46 })
47 }
48
49 /// Returns the value of the pi number with precision `p` using rounding mode `rm`.
50 /// Precision is rounded upwards to the word size.
51 ///
52 /// ## Errors
53 ///
54 /// - MemoryAllocation: failed to allocate memory for mantissa.
55 /// - InvalidArgument: the precision is incorrect.
56 pub(crate) fn pi_num(&mut self, p: usize, rm: RoundingMode) -> Result<BigFloatNumber, Error> {
57 let p = round_p(p);
58 self.pi.for_prec(p, rm)
59 }
60
61 /// Returns the value of the Euler number with precision `p` using rounding mode `rm`.
62 /// Precision is rounded upwards to the word size.
63 ///
64 /// ## Errors
65 ///
66 /// - MemoryAllocation: failed to allocate memory for mantissa.
67 /// - InvalidArgument: the precision is incorrect.
68 pub(crate) fn e_num(&mut self, p: usize, rm: RoundingMode) -> Result<BigFloatNumber, Error> {
69 let p = round_p(p);
70 self.e.for_prec(p, rm)
71 }
72
73 /// Returns the value of the natural logarithm of 2 with precision `p` using rounding mode `rm`.
74 /// Precision is rounded upwards to the word size.
75 ///
76 /// ## Errors
77 ///
78 /// - MemoryAllocation: failed to allocate memory for mantissa.
79 /// - InvalidArgument: the precision is incorrect.
80 pub(crate) fn ln_2_num(&mut self, p: usize, rm: RoundingMode) -> Result<BigFloatNumber, Error> {
81 let p = round_p(p);
82 self.ln2.for_prec(p, rm)
83 }
84
85 /// Returns the value of the natural logarithm of 10 with precision `p` using rounding mode `rm`.
86 /// Precision is rounded upwards to the word size.
87 ///
88 /// ## Errors
89 ///
90 /// - MemoryAllocation: failed to allocate memory for mantissa.
91 /// - InvalidArgument: the precision is incorrect.
92 pub(crate) fn ln_10_num(
93 &mut self,
94 p: usize,
95 rm: RoundingMode,
96 ) -> Result<BigFloatNumber, Error> {
97 let p = round_p(p);
98 self.ln10.for_prec(p, rm)
99 }
100
101 /// Returns the value of the pi number with precision `p` using rounding mode `rm`.
102 /// Precision is rounded upwards to the word size.
103 pub fn pi(&mut self, p: usize, rm: RoundingMode) -> BigFloat {
104 match self.pi_num(p, rm) {
105 Ok(v) => v.into(),
106 Err(e) => BigFloat::nan(Some(e)),
107 }
108 }
109
110 /// Returns the value of the Euler number with precision `p` using rounding mode `rm`.
111 /// Precision is rounded upwards to the word size.
112 pub fn e(&mut self, p: usize, rm: RoundingMode) -> BigFloat {
113 match self.e_num(p, rm) {
114 Ok(v) => v.into(),
115 Err(e) => BigFloat::nan(Some(e)),
116 }
117 }
118
119 /// Returns the value of the natural logarithm of 2 with precision `p` using rounding mode `rm`.
120 /// Precision is rounded upwards to the word size.
121 pub fn ln_2(&mut self, p: usize, rm: RoundingMode) -> BigFloat {
122 match self.ln_2_num(p, rm) {
123 Ok(v) => v.into(),
124 Err(e) => BigFloat::nan(Some(e)),
125 }
126 }
127
128 /// Returns the value of the natural logarithm of 10 with precision `p` using rounding mode `rm`.
129 /// Precision is rounded upwards to the word size.
130 pub fn ln_10(&mut self, p: usize, rm: RoundingMode) -> BigFloat {
131 match self.ln_10_num(p, rm) {
132 Ok(v) => v.into(),
133 Err(e) => BigFloat::nan(Some(e)),
134 }
135 }
136
137 /// Return powers of 10: 100, 10000, 100000000, ...
138 pub(crate) fn tenpowers(&mut self, p: usize) -> Result<&[(WordBuf, WordBuf, usize)], Error> {
139 if p >= self.tenpowers.len() {
140 Mantissa::compute_tenpowers(&mut self.tenpowers, p)?;
141 }
142
143 Ok(&self.tenpowers)
144 }
145}